diff --git a/.gitignore b/.gitignore index 125c7db4..9de1c76b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,15 @@ -# OS -.DS_Store - -# Editors -*~ - -# Eclipse -.metadata/ -.settings/ -bin/ -target/ - -# Java -.class - +# OS +.DS_Store + +# Editors +*~ + +# Eclipse +.metadata/ +bin/ +target/ +build/ + +# Java +.class + diff --git a/README.md b/README.md index 3bcc2ed3..fc2b14b6 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -simplJava - S.IM.PL in Java -========= - -S.IM.PL is an architecture that aims to let you simply transfer information between programming languages. -(Ideally with no muss, no fuss, and little boilerplate!) - -How does it do this? It allows you to: -* Serialize *everything* into *every* format -* Deserialize *every* format into the language of your choice -* Translate your object representations accross languages. - -For more information, hop onto #InterfaceEcologyLab's IRC channel (on Freenode) , or send an email to tom.white@outlook.com +simplJava - S.IM.PL in Java +========= + +S.IM.PL is an architecture that aims to let you simply transfer information between programming languages. +(Ideally with no muss, no fuss, and little boilerplate!) + +How does it do this? It allows you to: +* Serialize *everything* into *every* format +* Deserialize *every* format into the language of your choice +* Translate your object representations accross languages. + +##Look at the [simpl wiki](https://github.com/ecologylab/simpl/wiki) for more information. diff --git a/SimplTutorial/.classpath b/SimplTutorial/.classpath index 32e5c11e..780132ca 100644 --- a/SimplTutorial/.classpath +++ b/SimplTutorial/.classpath @@ -1,8 +1,10 @@ - - - - - - - - + + + + + + + + + + diff --git a/SimplTutorial/.project b/SimplTutorial/.project index 67626a3f..2c508332 100644 --- a/SimplTutorial/.project +++ b/SimplTutorial/.project @@ -1,17 +1,17 @@ - - - SimplTutorial - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - + + + SimplTutorial + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/SimplTutorial/src/ecologylab/tutorials/game/Coordinate.java b/SimplTutorial/src/ecologylab/tutorials/game/Coordinate.java index ebd8f3be..98d8c8b9 100644 --- a/SimplTutorial/src/ecologylab/tutorials/game/Coordinate.java +++ b/SimplTutorial/src/ecologylab/tutorials/game/Coordinate.java @@ -1,25 +1,25 @@ -package ecologylab.tutorials.game; - -import ecologylab.serialization.annotations.*; - -public class Coordinate { - - @simpl_scalar - public double x; - - @simpl_scalar - public double y; - - public Coordinate(){} - - public Coordinate(double _x, double _y){ - x = _x; - y = _y; - } - - public boolean equals(Object other){ - Coordinate o = (Coordinate) other; - return (o.x == this.x && o.y == this.y); - - } -} +package ecologylab.tutorials.game; + +import ecologylab.serialization.annotations.*; + +public class Coordinate { + + @simpl_scalar + public double x; + + @simpl_scalar + public double y; + + public Coordinate(){} + + public Coordinate(double _x, double _y){ + x = _x; + y = _y; + } + + public boolean equals(Object other){ + Coordinate o = (Coordinate) other; + return (o.x == this.x && o.y == this.y); + + } +} diff --git a/SimplTutorial/src/ecologylab/tutorials/game/GameData.java b/SimplTutorial/src/ecologylab/tutorials/game/GameData.java index e02f0386..172a248a 100644 --- a/SimplTutorial/src/ecologylab/tutorials/game/GameData.java +++ b/SimplTutorial/src/ecologylab/tutorials/game/GameData.java @@ -1,52 +1,52 @@ -package ecologylab.tutorials.game; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.*; -import java.util.ArrayList; - -public class GameData extends ElementState -{ - @simpl_scalar - protected long timestamp; - - /** Number of game cycles remaining. */ - @simpl_scalar - protected int cycRem; - - /** - * Indicates that, if the game is running, it should be paused; by default, the game starts this - * way and a user needs to activate it. - */ - @simpl_scalar - protected boolean paused = false; - - @simpl_scalar - protected boolean loaded = false; - - /** - * Game state flag indicating that the game is currently executing play cycles. - */ - @simpl_scalar - protected boolean running = false; - - /** Game state flag indicating that the players have won the game. */ - @simpl_scalar - protected boolean won = false; - - /** List of Threat objects. */ - - @simpl_classes( - { Threat.class, SingleSeekerThreat.class, OrbitingThreat.class, RepellableThreat.class, - PatrollingThreat.class }) - @simpl_collection - protected ArrayList threats = new ArrayList(); - - - @simpl_scalar - protected double score = 0; - - /** No-argument constructor, required for ElementState. */ - public GameData() - { - super(); - } +package ecologylab.tutorials.game; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.*; +import java.util.ArrayList; + +public class GameData extends ElementState +{ + @simpl_scalar + protected long timestamp; + + /** Number of game cycles remaining. */ + @simpl_scalar + protected int cycRem; + + /** + * Indicates that, if the game is running, it should be paused; by default, the game starts this + * way and a user needs to activate it. + */ + @simpl_scalar + protected boolean paused = false; + + @simpl_scalar + protected boolean loaded = false; + + /** + * Game state flag indicating that the game is currently executing play cycles. + */ + @simpl_scalar + protected boolean running = false; + + /** Game state flag indicating that the players have won the game. */ + @simpl_scalar + protected boolean won = false; + + /** List of Threat objects. */ + + @simpl_classes( + { Threat.class, SingleSeekerThreat.class, OrbitingThreat.class, RepellableThreat.class, + PatrollingThreat.class }) + @simpl_collection + protected ArrayList threats = new ArrayList(); + + + @simpl_scalar + protected double score = 0; + + /** No-argument constructor, required for ElementState. */ + public GameData() + { + super(); + } } \ No newline at end of file diff --git a/SimplTutorial/src/ecologylab/tutorials/game/OrbitingThreat.java b/SimplTutorial/src/ecologylab/tutorials/game/OrbitingThreat.java index abd6158f..58486610 100644 --- a/SimplTutorial/src/ecologylab/tutorials/game/OrbitingThreat.java +++ b/SimplTutorial/src/ecologylab/tutorials/game/OrbitingThreat.java @@ -1,22 +1,22 @@ -/** - * - */ -package ecologylab.tutorials.game; - -import ecologylab.serialization.annotations.*; - -/** - * A special predator that finds a goal and stays near it. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ - -@simpl_inherit -@simpl_tag("ot") -public class OrbitingThreat extends Threat -{ - /** Constructor stub for XML translation. */ - public OrbitingThreat() - { - } -} +/** + * + */ +package ecologylab.tutorials.game; + +import ecologylab.serialization.annotations.*; + +/** + * A special predator that finds a goal and stays near it. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ + +@simpl_inherit +@simpl_tag("ot") +public class OrbitingThreat extends Threat +{ + /** Constructor stub for XML translation. */ + public OrbitingThreat() + { + } +} diff --git a/SimplTutorial/src/ecologylab/tutorials/game/PatrollingThreat.java b/SimplTutorial/src/ecologylab/tutorials/game/PatrollingThreat.java index 590bf9f5..efce11e8 100644 --- a/SimplTutorial/src/ecologylab/tutorials/game/PatrollingThreat.java +++ b/SimplTutorial/src/ecologylab/tutorials/game/PatrollingThreat.java @@ -1,25 +1,25 @@ -/** - * - */ -package ecologylab.tutorials.game; - -import ecologylab.serialization.annotations.*; - -/** - * A special predator that moves from goal to goal when not chasing the seekers. - * - * The purpose of this predator is to help give the predator flocks some intelligence and get them - * to move around a bit instead of clumping too much due to their flocking behavior. - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -@simpl_inherit -@simpl_tag("pt") -public class PatrollingThreat extends Threat -{ - /** Constructor stub for XML translation. */ - public PatrollingThreat() - { - } -} +/** + * + */ +package ecologylab.tutorials.game; + +import ecologylab.serialization.annotations.*; + +/** + * A special predator that moves from goal to goal when not chasing the seekers. + * + * The purpose of this predator is to help give the predator flocks some intelligence and get them + * to move around a bit instead of clumping too much due to their flocking behavior. + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +@simpl_inherit +@simpl_tag("pt") +public class PatrollingThreat extends Threat +{ + /** Constructor stub for XML translation. */ + public PatrollingThreat() + { + } +} diff --git a/SimplTutorial/src/ecologylab/tutorials/game/PolymorphicJavaTutorial.java b/SimplTutorial/src/ecologylab/tutorials/game/PolymorphicJavaTutorial.java index 33c5fb7e..20a24d26 100644 --- a/SimplTutorial/src/ecologylab/tutorials/game/PolymorphicJavaTutorial.java +++ b/SimplTutorial/src/ecologylab/tutorials/game/PolymorphicJavaTutorial.java @@ -1,38 +1,38 @@ -package ecologylab.tutorials.game; - -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.Format; - -public class PolymorphicJavaTutorial { - - /** - * @param args - */ - public static void main(String[] args) { - // TODO Auto-generated method stub -try - { - /* - * Get translation scope - */ - TranslationScope tScope = get(); - - SimplTypesScope example = SimplTypesScope.get("ThreatTest", Threat.class, Coordinate.class, OrbitingThreat.class, PatrollingThreat.class, RepellableThreat.class); - - - - - - - - example.deserialize(test, Format.XML); - - - } - catch (Exception e) - { - e.printStackTrace(); - } - } - -} +package ecologylab.tutorials.game; + +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; + +public class PolymorphicJavaTutorial { + + /** + * @param args + */ + public static void main(String[] args) { + // TODO Auto-generated method stub +try + { + /* + * Get translation scope + */ + //TranslationScope tScope = get(); + + SimplTypesScope example = SimplTypesScope.get("ThreatTest", Threat.class, Coordinate.class, OrbitingThreat.class, PatrollingThreat.class, RepellableThreat.class); + + + + + + + + //example.deserialize(test, Format.XML); + + + } + catch (Exception e) + { + e.printStackTrace(); + } + } + +} diff --git a/SimplTutorial/src/ecologylab/tutorials/game/RepellableThreat.java b/SimplTutorial/src/ecologylab/tutorials/game/RepellableThreat.java index 250296c5..77fbabfc 100644 --- a/SimplTutorial/src/ecologylab/tutorials/game/RepellableThreat.java +++ b/SimplTutorial/src/ecologylab/tutorials/game/RepellableThreat.java @@ -1,27 +1,27 @@ -/* - * Added by Qing Xing - */ - -package ecologylab.tutorials.game; - -import ecologylab.serialization.annotations.*; -/** - * Predators are Targetters that hunt down SeekerAvatars in the game. Their in-game behavior is to - * search (by looking in circles) for nearby SeekerAvatars, and then moving to touch those - * SeekerAvatars (and thus make them out). - * - * @author Zachary O. Toups (zach@ecologylab.net) - * @author Qing Xing - */ -public @simpl_inherit -@simpl_tag("nt") -class RepellableThreat extends Threat -{ - /** - * No-argument constructor, required for ElementState. - */ - public RepellableThreat() - { - super(); - } -} +/* + * Added by Qing Xing + */ + +package ecologylab.tutorials.game; + +import ecologylab.serialization.annotations.*; +/** + * Predators are Targetters that hunt down SeekerAvatars in the game. Their in-game behavior is to + * search (by looking in circles) for nearby SeekerAvatars, and then moving to touch those + * SeekerAvatars (and thus make them out). + * + * @author Zachary O. Toups (zach@ecologylab.net) + * @author Qing Xing + */ +public @simpl_inherit +@simpl_tag("nt") +class RepellableThreat extends Threat +{ + /** + * No-argument constructor, required for ElementState. + */ + public RepellableThreat() + { + super(); + } +} diff --git a/SimplTutorial/src/ecologylab/tutorials/game/SingleSeekerThreat.java b/SimplTutorial/src/ecologylab/tutorials/game/SingleSeekerThreat.java index a38508f2..1594732a 100644 --- a/SimplTutorial/src/ecologylab/tutorials/game/SingleSeekerThreat.java +++ b/SimplTutorial/src/ecologylab/tutorials/game/SingleSeekerThreat.java @@ -1,26 +1,26 @@ -/** - * - */ -package ecologylab.tutorials.game; - -import ecologylab.serialization.annotations.*; - -/** - * @author Zachary O. Toups (toupsz@ecologylab.net) - * - */ - -@simpl_inherit -@simpl_tag("sst") -public class SingleSeekerThreat extends Threat -{ - @simpl_scalar - int targetOrd; - - /** - * Default Constructor - */ - public SingleSeekerThreat() - { - } -} +/** + * + */ +package ecologylab.tutorials.game; + +import ecologylab.serialization.annotations.*; + +/** + * @author Zachary O. Toups (toupsz@ecologylab.net) + * + */ + +@simpl_inherit +@simpl_tag("sst") +public class SingleSeekerThreat extends Threat +{ + @simpl_scalar + int targetOrd; + + /** + * Default Constructor + */ + public SingleSeekerThreat() + { + } +} diff --git a/SimplTutorial/src/ecologylab/tutorials/game/Threat.java b/SimplTutorial/src/ecologylab/tutorials/game/Threat.java index b6864550..72e689b8 100644 --- a/SimplTutorial/src/ecologylab/tutorials/game/Threat.java +++ b/SimplTutorial/src/ecologylab/tutorials/game/Threat.java @@ -1,47 +1,47 @@ -/* - * Created on Feb 13, 2005 - */ - -package ecologylab.tutorials.game; - - -//import tutorials.polymorphic.rogue.game2d.entity.Entity; -import ecologylab.serialization.annotations.*; - -/** - * Threats are Targetters that hunt down SeekerAvatars in the game. Their in-game behavior is to - * search (by looking in circles) for nearby SeekerAvatars, and then moving to touch those - * SeekerAvatars (and thus make them out). - * - * @author Zachary O. Toups (zach@ecologylab.net) - * @author William Hamilton (bill@ecologylab.net) - */ -@simpl_inherit -@simpl_tag("t") -public class Threat -{ - @simpl_scalar - public double tVal; - @simpl_scalar - public String id; - @simpl_scalar - public int ord; - - @simpl_composite - public Coordinate dir; - - @simpl_composite - public Coordinate vel; - - @simpl_composite - public Coordinate pos; - - - /** - * No-argument constructor, required for ElementState. - */ - public Threat() - { - super(); - } +/* + * Created on Feb 13, 2005 + */ + +package ecologylab.tutorials.game; + + +//import tutorials.polymorphic.rogue.game2d.entity.Entity; +import ecologylab.serialization.annotations.*; + +/** + * Threats are Targetters that hunt down SeekerAvatars in the game. Their in-game behavior is to + * search (by looking in circles) for nearby SeekerAvatars, and then moving to touch those + * SeekerAvatars (and thus make them out). + * + * @author Zachary O. Toups (zach@ecologylab.net) + * @author William Hamilton (bill@ecologylab.net) + */ +@simpl_inherit +@simpl_tag("t") +public class Threat +{ + @simpl_scalar + public double tVal; + @simpl_scalar + public String id; + @simpl_scalar + public int ord; + + @simpl_composite + public Coordinate dir; + + @simpl_composite + public Coordinate vel; + + @simpl_composite + public Coordinate pos; + + + /** + * No-argument constructor, required for ElementState. + */ + public Threat() + { + super(); + } } \ No newline at end of file diff --git a/SimplTutorial/src/ecologylab/tutorials/game/test.xml b/SimplTutorial/src/ecologylab/tutorials/game/test.xml index 8ab90d9c..99f6bc5e 100644 --- a/SimplTutorial/src/ecologylab/tutorials/game/test.xml +++ b/SimplTutorial/src/ecologylab/tutorials/game/test.xml @@ -1,46 +1,46 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SimplTutorial/src/ecologylab/tutorials/rss/Channel.java b/SimplTutorial/src/ecologylab/tutorials/rss/Channel.java index b69e3545..c3ee1312 100644 --- a/SimplTutorial/src/ecologylab/tutorials/rss/Channel.java +++ b/SimplTutorial/src/ecologylab/tutorials/rss/Channel.java @@ -1,31 +1,31 @@ - //Channel.java - -package ecologylab.tutorials.rss; - -import java.util.ArrayList; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.library.rss.Item; - -public class Channel extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; - - @simpl_nowrap - @simpl_collection("item") - ArrayList items; - - public Channel() { } - - public ArrayList getItems() - { - return items; - } + //Channel.java + +package ecologylab.tutorials.rss; + +import java.util.ArrayList; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.library.rss.Item; + +public class Channel extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; + + @simpl_nowrap + @simpl_collection("item") + ArrayList items; + + public Channel() { } + + public ArrayList getItems() + { + return items; + } } \ No newline at end of file diff --git a/SimplTutorial/src/ecologylab/tutorials/rss/Item.java b/SimplTutorial/src/ecologylab/tutorials/rss/Item.java index 2161967c..0a56df70 100644 --- a/SimplTutorial/src/ecologylab/tutorials/rss/Item.java +++ b/SimplTutorial/src/ecologylab/tutorials/rss/Item.java @@ -1,75 +1,75 @@ - //Item.java - -package ecologylab.tutorials.rss; - -import java.util.ArrayList; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_collection; - -public class Item extends ElementState -{ - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public ParsedURL getLink() { - return link; - } - - public void setLink(ParsedURL link) { - this.link = link; - } - - public ParsedURL getGuid() { - return guid; - } - - public void setGuid(ParsedURL guid) { - this.guid = guid; - } - - public String getAuthor() { - return author; - } - - public void setAuthor(String author) { - this.author = author; - } - - public ArrayList getCategorySet() { - return categorySet; - } - - public void setCategorySet(ArrayList categorySet) { - this.categorySet = categorySet; - } - -@simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL guid; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String author; - - @simpl_nowrap - @simpl_collection("category") - ArrayList categorySet; - - public Item() {} + //Item.java + +package ecologylab.tutorials.rss; + +import java.util.ArrayList; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_collection; + +public class Item extends ElementState +{ + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public ParsedURL getLink() { + return link; + } + + public void setLink(ParsedURL link) { + this.link = link; + } + + public ParsedURL getGuid() { + return guid; + } + + public void setGuid(ParsedURL guid) { + this.guid = guid; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public ArrayList getCategorySet() { + return categorySet; + } + + public void setCategorySet(ArrayList categorySet) { + this.categorySet = categorySet; + } + +@simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL guid; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String author; + + @simpl_nowrap + @simpl_collection("category") + ArrayList categorySet; + + public Item() {} } \ No newline at end of file diff --git a/SimplTutorial/src/ecologylab/tutorials/rss/MonomorphicJavaTutorial.java b/SimplTutorial/src/ecologylab/tutorials/rss/MonomorphicJavaTutorial.java index a62c6174..27baba10 100644 --- a/SimplTutorial/src/ecologylab/tutorials/rss/MonomorphicJavaTutorial.java +++ b/SimplTutorial/src/ecologylab/tutorials/rss/MonomorphicJavaTutorial.java @@ -1,70 +1,70 @@ -package ecologylab.tutorials.rss; -import ecologylab.tutorials.rss.*; -import java.io.IOException; -import ecologylab.serialization.*; -import ecologylab.serialization.formatenums.StringFormat; - -import java.net.URL; -import ecologylab.net.*; -import java.io.DataInputStream; -import java.io.InputStream; -import java.io.BufferedInputStream; -import java.net.MalformedURLException; - -public class MonomorphicJavaTutorial { - public static void main(String[] args) throws Exception - { - - SimplTypesScope rssTranslations = RssTranslations.get(); - URL url = new URL("http://www.xkcd.com/rss.xml"); - String rssContent = readURL(url); - - System.out.println("Raw RSS Feed:"); - System.out.println(rssContent); - - Rss feed = (Rss) rssTranslations.deserialize(rssContent, StringFormat.XML); - - System.out.println("\nFeed translated back to xml by s.im.pl serialization:"); - System.out.println(SimplTypesScope.serialize(feed, StringFormat.XML)); - - Item ecologylabItem = new Item(); - ecologylabItem.setTitle("The Interface Ecology Lab"); - ecologylabItem.setDescription("Highlights the cool research going on at the lab."); - ecologylabItem.setAuthor("Dr. Andruid Kerne"); - ecologylabItem.setLink(new ParsedURL(new URL("http://www.ecologylab.net"))); - -// feed.getChannel().getItems().add(0, ecologylabItem); - - // System.out.println("\nFeed translated to xml with our added item:"); - // System.out.println(feed.serialize()); - } - - public static String readURL(URL earl) throws MalformedURLException, IOException{ - InputStream is = null; - DataInputStream dis; - String line; - - StringBuilder sb = new StringBuilder(); - - try { - is = earl.openStream(); // throws an IOException - dis = new DataInputStream(new BufferedInputStream(is)); - - while ((line = dis.readLine()) != null) { - sb.append(line); - } - - } catch (MalformedURLException mue) { - mue.printStackTrace(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } finally { - try { - is.close(); - } catch (IOException ioe) { - // nothing to see here - } - } - return sb.toString(); - } -} +package ecologylab.tutorials.rss; +import ecologylab.tutorials.rss.*; +import java.io.IOException; +import ecologylab.serialization.*; +import ecologylab.serialization.formatenums.StringFormat; + +import java.net.URL; +import ecologylab.net.*; +import java.io.DataInputStream; +import java.io.InputStream; +import java.io.BufferedInputStream; +import java.net.MalformedURLException; + +public class MonomorphicJavaTutorial { + public static void main(String[] args) throws Exception + { + + SimplTypesScope rssTranslations = RssTranslations.get(); + URL url = new URL("http://www.xkcd.com/rss.xml"); + String rssContent = readURL(url); + + System.out.println("Raw RSS Feed:"); + System.out.println(rssContent); + + Rss feed = (Rss) rssTranslations.deserialize(rssContent, StringFormat.XML); + + System.out.println("\nFeed translated back to xml by s.im.pl serialization:"); + System.out.println(SimplTypesScope.serialize(feed, StringFormat.XML)); + + Item ecologylabItem = new Item(); + ecologylabItem.setTitle("The Interface Ecology Lab"); + ecologylabItem.setDescription("Highlights the cool research going on at the lab."); + ecologylabItem.setAuthor("Dr. Andruid Kerne"); + ecologylabItem.setLink(new ParsedURL(new URL("http://www.ecologylab.net"))); + +// feed.getChannel().getItems().add(0, ecologylabItem); + + // System.out.println("\nFeed translated to xml with our added item:"); + // System.out.println(feed.serialize()); + } + + public static String readURL(URL earl) throws MalformedURLException, IOException{ + InputStream is = null; + DataInputStream dis; + String line; + + StringBuilder sb = new StringBuilder(); + + try { + is = earl.openStream(); // throws an IOException + dis = new DataInputStream(new BufferedInputStream(is)); + + while ((line = dis.readLine()) != null) { + sb.append(line); + } + + } catch (MalformedURLException mue) { + mue.printStackTrace(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } finally { + try { + is.close(); + } catch (IOException ioe) { + // nothing to see here + } + } + return sb.toString(); + } +} diff --git a/SimplTutorial/src/ecologylab/tutorials/rss/Rss.java b/SimplTutorial/src/ecologylab/tutorials/rss/Rss.java index ddba4dd3..085324a8 100644 --- a/SimplTutorial/src/ecologylab/tutorials/rss/Rss.java +++ b/SimplTutorial/src/ecologylab/tutorials/rss/Rss.java @@ -1,16 +1,16 @@ - //Rss.java - -package ecologylab.tutorials.rss; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.library.rss.Channel; - -public class Rss extends ElementState -{ - @simpl_scalar float version; - @simpl_composite Channel channel; - - public Rss() {} + //Rss.java + +package ecologylab.tutorials.rss; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.library.rss.Channel; + +public class Rss extends ElementState +{ + @simpl_scalar float version; + @simpl_composite Channel channel; + + public Rss() {} } \ No newline at end of file diff --git a/SimplTutorial/src/ecologylab/tutorials/rss/RssTranslations.java b/SimplTutorial/src/ecologylab/tutorials/rss/RssTranslations.java index 02837955..56d9e088 100644 --- a/SimplTutorial/src/ecologylab/tutorials/rss/RssTranslations.java +++ b/SimplTutorial/src/ecologylab/tutorials/rss/RssTranslations.java @@ -1,14 +1,14 @@ - //RssTranslations.java - -package ecologylab.tutorials.rss; - -import ecologylab.generic.Debug; -import ecologylab.serialization.SimplTypesScope; - -public class RssTranslations extends Debug -{ - public static SimplTypesScope get() - { - return SimplTypesScope.get("rss", Rss.class, Channel.class, Item.class); - } + //RssTranslations.java + +package ecologylab.tutorials.rss; + +import ecologylab.generic.Debug; +import ecologylab.serialization.SimplTypesScope; + +public class RssTranslations extends Debug +{ + public static SimplTypesScope get() + { + return SimplTypesScope.get("rss", Rss.class, Channel.class, Item.class); + } } \ No newline at end of file diff --git a/SimplTutorial/test/ecologylab/tutorials/game/ThreatTest.java b/SimplTutorial/test/ecologylab/tutorials/game/ThreatTest.java index cf6ec72e..8985e0ae 100644 --- a/SimplTutorial/test/ecologylab/tutorials/game/ThreatTest.java +++ b/SimplTutorial/test/ecologylab/tutorials/game/ThreatTest.java @@ -1,61 +1,60 @@ -package ecologylab.tutorials.game; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -import java.io.File; -import java.nio.file.*; - -public class ThreatTest { - - @Test - public void testRoundtripOnThreats() throws SIMPLTranslationException { - Threat tom = new Threat(); - - tom.id = "a"; - tom.ord = 13; - tom.tVal = 3.14; - - tom.dir = new Coordinate(1,2); - tom.vel = new Coordinate(3,4); - tom.pos = new Coordinate(5,6); - - String result = SimplTypesScope.serialize(tom, StringFormat.XML).toString(); - - System.out.println(result); - - SimplTypesScope example = SimplTypesScope.get("ThreatTest", Threat.class, Coordinate.class); - Object XMLresult = example.deserialize(result, StringFormat.XML); - - Threat r = (Threat) XMLresult; - - assertEquals(r.dir, tom.dir); - assertEquals(r.vel, tom.vel); - assertEquals(r.pos, tom.pos); - - assertEquals(r.id, tom.id); - assertEquals(r.ord, tom.ord); - assertEquals(r.tVal, tom.tVal,0.1); - - } - - @Test - public void testDeserializationOfTutorial() throws SIMPLTranslationException - { - SimplTypesScope example = SimplTypesScope.get("ThreatTest", Threat.class, Coordinate.class, OrbitingThreat.class, PatrollingThreat.class, RepellableThreat.class); - - File test = new File("SimplTutorial/test/ecologylab/tutorials/game/test.xml"); - - example.deserialize(test, Format.XML); - - // todo put validation here. - - } - -} +package ecologylab.tutorials.game; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +import java.io.File; + +public class ThreatTest { + + @Test + public void testRoundtripOnThreats() throws SIMPLTranslationException { + Threat tom = new Threat(); + + tom.id = "a"; + tom.ord = 13; + tom.tVal = 3.14; + + tom.dir = new Coordinate(1,2); + tom.vel = new Coordinate(3,4); + tom.pos = new Coordinate(5,6); + + String result = SimplTypesScope.serialize(tom, StringFormat.XML).toString(); + + System.out.println(result); + + SimplTypesScope example = SimplTypesScope.get("ThreatTest", Threat.class, Coordinate.class); + Object XMLresult = example.deserialize(result, StringFormat.XML); + + Threat r = (Threat) XMLresult; + + assertEquals(r.dir, tom.dir); + assertEquals(r.vel, tom.vel); + assertEquals(r.pos, tom.pos); + + assertEquals(r.id, tom.id); + assertEquals(r.ord, tom.ord); + assertEquals(r.tVal, tom.tVal,0.1); + + } + + @Test + public void testDeserializationOfTutorial() throws SIMPLTranslationException + { + SimplTypesScope example = SimplTypesScope.get("ThreatTest", Threat.class, Coordinate.class, OrbitingThreat.class, PatrollingThreat.class, RepellableThreat.class); + + File test = new File("SimplTutorial/test/ecologylab/tutorials/game/test.xml"); + + example.deserialize(test, Format.XML); + + // todo put validation here. + + } + +} diff --git a/lib/.project b/lib/.project new file mode 100644 index 00000000..4a2abd62 --- /dev/null +++ b/lib/.project @@ -0,0 +1,11 @@ + + + simpl-lib + + + + + + + + diff --git a/lib/ST-4.0.7.jar b/lib/ST-4.0.7.jar new file mode 100644 index 00000000..8b2baa1d Binary files /dev/null and b/lib/ST-4.0.7.jar differ diff --git a/simplCore/lib/WebSocket.jar b/lib/WebSocket.jar similarity index 100% rename from simplCore/lib/WebSocket.jar rename to lib/WebSocket.jar diff --git a/simplCore/lib/ant-contrib-1.0b3.jar b/lib/ant-contrib-1.0b3.jar similarity index 100% rename from simplCore/lib/ant-contrib-1.0b3.jar rename to lib/ant-contrib-1.0b3.jar diff --git a/simplCore/lib/ant4eclipse-0.5.0.rc1.jar b/lib/ant4eclipse-0.5.0.rc1.jar similarity index 100% rename from simplCore/lib/ant4eclipse-0.5.0.rc1.jar rename to lib/ant4eclipse-0.5.0.rc1.jar diff --git a/simplCore/lib/antform.jar b/lib/antform.jar similarity index 100% rename from simplCore/lib/antform.jar rename to lib/antform.jar diff --git a/lib/antlr-3.5-complete.jar b/lib/antlr-3.5-complete.jar new file mode 100644 index 00000000..171dc2fa Binary files /dev/null and b/lib/antlr-3.5-complete.jar differ diff --git a/simplCore/lib/ecj-3.6.jar b/lib/ecj-3.6.jar similarity index 100% rename from simplCore/lib/ecj-3.6.jar rename to lib/ecj-3.6.jar diff --git a/simplTests/lib/guava-14.0-rc1.jar b/lib/guava-14.0-rc1.jar similarity index 100% rename from simplTests/lib/guava-14.0-rc1.jar rename to lib/guava-14.0-rc1.jar diff --git a/simplCore/lib/jackson-core-lgpl-1.7.8.jar b/lib/jackson-core-lgpl-1.7.8.jar similarity index 100% rename from simplCore/lib/jackson-core-lgpl-1.7.8.jar rename to lib/jackson-core-lgpl-1.7.8.jar diff --git a/simplTranslators/lib/javaparser-1.0.8.jar b/lib/javaparser-1.0.8.jar similarity index 100% rename from simplTranslators/lib/javaparser-1.0.8.jar rename to lib/javaparser-1.0.8.jar diff --git a/simplCore/lib/json_simple-1.1.jar b/lib/json_simple-1.1.jar similarity index 100% rename from simplCore/lib/json_simple-1.1.jar rename to lib/json_simple-1.1.jar diff --git a/simplCore/lib/junit-4.11.jar b/lib/junit-4.11.jar similarity index 100% rename from simplCore/lib/junit-4.11.jar rename to lib/junit-4.11.jar diff --git a/simplCore/lib/log4j-1.2.17.jar b/lib/log4j-1.2.17.jar similarity index 100% rename from simplCore/lib/log4j-1.2.17.jar rename to lib/log4j-1.2.17.jar diff --git a/simplCore/lib/org.eclipse.osgi_3.6.0.v20100517.jar b/lib/org.eclipse.osgi_3.6.0.v20100517.jar similarity index 100% rename from simplCore/lib/org.eclipse.osgi_3.6.0.v20100517.jar rename to lib/org.eclipse.osgi_3.6.0.v20100517.jar diff --git a/simplTranslators/lib/postgresql-8.4-701.jdbc4.jar b/lib/postgresql-8.4-701.jdbc4.jar similarity index 100% rename from simplTranslators/lib/postgresql-8.4-701.jdbc4.jar rename to lib/postgresql-8.4-701.jdbc4.jar diff --git a/lib/simpl-build-common.xml b/lib/simpl-build-common.xml new file mode 100644 index 00000000..4d11a79a --- /dev/null +++ b/lib/simpl-build-common.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/simpl-projects.xml b/lib/simpl-projects.xml new file mode 100644 index 00000000..8ad67e41 --- /dev/null +++ b/lib/simpl-projects.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + diff --git a/simplPlatformSpecifics/Android/.classpath b/simplAndroidSpecifics/.classpath similarity index 81% rename from simplPlatformSpecifics/Android/.classpath rename to simplAndroidSpecifics/.classpath index e75adda2..9ad879c1 100644 --- a/simplPlatformSpecifics/Android/.classpath +++ b/simplAndroidSpecifics/.classpath @@ -1,9 +1,10 @@ - - - - - - - - - + + + + + + + + + + diff --git a/simplPlatformSpecifics/Android/.project b/simplAndroidSpecifics/.project similarity index 96% rename from simplPlatformSpecifics/Android/.project rename to simplAndroidSpecifics/.project index 44141812..921d96cc 100644 --- a/simplPlatformSpecifics/Android/.project +++ b/simplAndroidSpecifics/.project @@ -1,33 +1,33 @@ - - - simplAndroidSpecifics - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - + + + simplAndroidSpecifics + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/simplPlatformSpecifics/Android/AndroidManifest.xml b/simplAndroidSpecifics/AndroidManifest.xml similarity index 97% rename from simplPlatformSpecifics/Android/AndroidManifest.xml rename to simplAndroidSpecifics/AndroidManifest.xml index d0964115..ef147dc6 100644 --- a/simplPlatformSpecifics/Android/AndroidManifest.xml +++ b/simplAndroidSpecifics/AndroidManifest.xml @@ -1,12 +1,12 @@ - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/simplPlatformSpecifics/Android/README b/simplAndroidSpecifics/README similarity index 98% rename from simplPlatformSpecifics/Android/README rename to simplAndroidSpecifics/README index e514bf51..0933ca84 100644 --- a/simplPlatformSpecifics/Android/README +++ b/simplAndroidSpecifics/README @@ -1,5 +1,5 @@ -The Interface Ecology Lab ( ecologylab.net ) has recently moved all code from svn to github. - -If this repository does not have a wiki, please look at the s.im.pl guide ( http://ecologylab.net/research/simplGuide/index.html ). - -Subscribe to meta-metadata developers group ( http://groups.google.com/group/metametadata/subscribe ), or s.im.pl api developers group ( http://groups.google.com/group/ecologylabAPI/subscribe ) to see our history and ask questions. +The Interface Ecology Lab ( ecologylab.net ) has recently moved all code from svn to github. + +If this repository does not have a wiki, please look at the s.im.pl guide ( http://ecologylab.net/research/simplGuide/index.html ). + +Subscribe to meta-metadata developers group ( http://groups.google.com/group/metametadata/subscribe ), or s.im.pl api developers group ( http://groups.google.com/group/ecologylabAPI/subscribe ) to see our history and ask questions. diff --git a/simplPlatformSpecifics/Android/default.properties b/simplAndroidSpecifics/default.properties similarity index 96% rename from simplPlatformSpecifics/Android/default.properties rename to simplAndroidSpecifics/default.properties index 1694c805..46945599 100644 --- a/simplPlatformSpecifics/Android/default.properties +++ b/simplAndroidSpecifics/default.properties @@ -1,12 +1,12 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system use, -# "build.properties", and override values to adapt the script to your -# project structure. - -# Project target. -target=android-9 -android.library=true +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-9 +android.library=true diff --git a/simplPlatformSpecifics/Android/libs/jWebSocketClientAPI-1.0.jar b/simplAndroidSpecifics/libs/jWebSocketClientAPI-1.0.jar similarity index 100% rename from simplPlatformSpecifics/Android/libs/jWebSocketClientAPI-1.0.jar rename to simplAndroidSpecifics/libs/jWebSocketClientAPI-1.0.jar diff --git a/simplPlatformSpecifics/Android/libs/jWebSocketCommon-1.0.jar b/simplAndroidSpecifics/libs/jWebSocketCommon-1.0.jar similarity index 100% rename from simplPlatformSpecifics/Android/libs/jWebSocketCommon-1.0.jar rename to simplAndroidSpecifics/libs/jWebSocketCommon-1.0.jar diff --git a/simplPlatformSpecifics/Android/libs/jWebSocketJavaSEClient-1.0.jar b/simplAndroidSpecifics/libs/jWebSocketJavaSEClient-1.0.jar similarity index 100% rename from simplPlatformSpecifics/Android/libs/jWebSocketJavaSEClient-1.0.jar rename to simplAndroidSpecifics/libs/jWebSocketJavaSEClient-1.0.jar diff --git a/simplPlatformSpecifics/Android/libs/jackson-core-asl-1.9.3.jar b/simplAndroidSpecifics/libs/jackson-core-asl-1.9.3.jar similarity index 100% rename from simplPlatformSpecifics/Android/libs/jackson-core-asl-1.9.3.jar rename to simplAndroidSpecifics/libs/jackson-core-asl-1.9.3.jar diff --git a/simplPlatformSpecifics/Android/libs/jackson-mapper-asl-1.9.3.jar b/simplAndroidSpecifics/libs/jackson-mapper-asl-1.9.3.jar similarity index 100% rename from simplPlatformSpecifics/Android/libs/jackson-mapper-asl-1.9.3.jar rename to simplAndroidSpecifics/libs/jackson-mapper-asl-1.9.3.jar diff --git a/simplPlatformSpecifics/Android/libs/javolution-5.5.1.jar b/simplAndroidSpecifics/libs/javolution-5.5.1.jar similarity index 100% rename from simplPlatformSpecifics/Android/libs/javolution-5.5.1.jar rename to simplAndroidSpecifics/libs/javolution-5.5.1.jar diff --git a/simplPlatformSpecifics/Android/libs/xml-addon.jar b/simplAndroidSpecifics/libs/xml-addon.jar similarity index 100% rename from simplPlatformSpecifics/Android/libs/xml-addon.jar rename to simplAndroidSpecifics/libs/xml-addon.jar diff --git a/simplPlatformSpecifics/Android/proguard.cfg b/simplAndroidSpecifics/proguard.cfg similarity index 96% rename from simplPlatformSpecifics/Android/proguard.cfg rename to simplAndroidSpecifics/proguard.cfg index b1cdf17b..f0b04dc3 100644 --- a/simplPlatformSpecifics/Android/proguard.cfg +++ b/simplAndroidSpecifics/proguard.cfg @@ -1,40 +1,40 @@ --optimizationpasses 5 --dontusemixedcaseclassnames --dontskipnonpubliclibraryclasses --dontpreverify --verbose --optimizations !code/simplification/arithmetic,!field/*,!class/merging/* - --keep public class * extends android.app.Activity --keep public class * extends android.app.Application --keep public class * extends android.app.Service --keep public class * extends android.content.BroadcastReceiver --keep public class * extends android.content.ContentProvider --keep public class * extends android.app.backup.BackupAgentHelper --keep public class * extends android.preference.Preference --keep public class com.android.vending.licensing.ILicensingService - --keepclasseswithmembernames class * { - native ; -} - --keepclasseswithmembers class * { - public (android.content.Context, android.util.AttributeSet); -} - --keepclasseswithmembers class * { - public (android.content.Context, android.util.AttributeSet, int); -} - --keepclassmembers class * extends android.app.Activity { - public void *(android.view.View); -} - --keepclassmembers enum * { - public static **[] values(); - public static ** valueOf(java.lang.String); -} - --keep class * implements android.os.Parcelable { - public static final android.os.Parcelable$Creator *; -} +-optimizationpasses 5 +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses +-dontpreverify +-verbose +-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* + +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Application +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers class * extends android.app.Activity { + public void *(android.view.View); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} diff --git a/simplPlatformSpecifics/Android/project.properties b/simplAndroidSpecifics/project.properties similarity index 96% rename from simplPlatformSpecifics/Android/project.properties rename to simplAndroidSpecifics/project.properties index 616f300c..02b865b0 100644 --- a/simplPlatformSpecifics/Android/project.properties +++ b/simplAndroidSpecifics/project.properties @@ -1,12 +1,12 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system use, -# "ant.properties", and override values to adapt the script to your -# project structure. - -android.library=true -# Project target. -target=android-16 +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "ant.properties", and override values to adapt the script to your +# project structure. + +android.library=true +# Project target. +target=android-16 diff --git a/simplPlatformSpecifics/Android/res/drawable-hdpi/icon.png b/simplAndroidSpecifics/res/drawable-hdpi/icon.png similarity index 100% rename from simplPlatformSpecifics/Android/res/drawable-hdpi/icon.png rename to simplAndroidSpecifics/res/drawable-hdpi/icon.png diff --git a/simplPlatformSpecifics/Android/res/drawable-ldpi/icon.png b/simplAndroidSpecifics/res/drawable-ldpi/icon.png similarity index 100% rename from simplPlatformSpecifics/Android/res/drawable-ldpi/icon.png rename to simplAndroidSpecifics/res/drawable-ldpi/icon.png diff --git a/simplPlatformSpecifics/Android/res/drawable-mdpi/icon.png b/simplAndroidSpecifics/res/drawable-mdpi/icon.png similarity index 100% rename from simplPlatformSpecifics/Android/res/drawable-mdpi/icon.png rename to simplAndroidSpecifics/res/drawable-mdpi/icon.png diff --git a/simplPlatformSpecifics/Android/res/layout/main.xml b/simplAndroidSpecifics/res/layout/main.xml similarity index 96% rename from simplPlatformSpecifics/Android/res/layout/main.xml rename to simplAndroidSpecifics/res/layout/main.xml index 3a5f117d..1e416f06 100644 --- a/simplPlatformSpecifics/Android/res/layout/main.xml +++ b/simplAndroidSpecifics/res/layout/main.xml @@ -1,12 +1,12 @@ - - - - + + + + diff --git a/simplPlatformSpecifics/Android/res/values/strings.xml b/simplAndroidSpecifics/res/values/strings.xml similarity index 96% rename from simplPlatformSpecifics/Android/res/values/strings.xml rename to simplAndroidSpecifics/res/values/strings.xml index f9ddbb88..60d4e166 100644 --- a/simplPlatformSpecifics/Android/res/values/strings.xml +++ b/simplAndroidSpecifics/res/values/strings.xml @@ -1,5 +1,5 @@ - - - Hello World! - - + + + Hello World! + + diff --git a/simplPlatformSpecifics/Android/src/ecologylab/appframework/types/prefs/MetaPrefColor.java b/simplAndroidSpecifics/src/ecologylab/appframework/types/prefs/MetaPrefColor.java similarity index 95% rename from simplPlatformSpecifics/Android/src/ecologylab/appframework/types/prefs/MetaPrefColor.java rename to simplAndroidSpecifics/src/ecologylab/appframework/types/prefs/MetaPrefColor.java index dc8a9cba..16c86ae3 100644 --- a/simplPlatformSpecifics/Android/src/ecologylab/appframework/types/prefs/MetaPrefColor.java +++ b/simplAndroidSpecifics/src/ecologylab/appframework/types/prefs/MetaPrefColor.java @@ -1,72 +1,72 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -//import java.awt.Color; -import android.graphics.Color; - -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.TypeRegistry; - -/** - * @author awebb - * - */ -public class MetaPrefColor extends MetaPref -{ - /** - * Default value for this MetaPref - */ - @simpl_scalar Color defaultValue; - - public static final ScalarType COLOR_SCALAR_TYPE = TypeRegistry.getScalarType(Color.class); - - public MetaPrefColor() - { - super(COLOR_SCALAR_TYPE); - } - - /** - * Gets the default value of a MetaPref. - * - * @return Default value of MetaPref, or Black if null. - */ - @Override - public Color getDefaultValue() - { - return (Color) ((defaultValue != null) ? defaultValue : Color.BLACK); - } - - /** - * Construct a new instance of the Pref that matches this. - * Use this to fill-in the default value. - * - * @return new Pref instance - */ - @Override - protected Pref getPrefInstance() - { - return new PrefColor(); - } - - /** - * Get max value; returns null for this type. - */ - @Override - public Color getMaxValue() - { - return null; - } - - /** - * Get min value; returns null for this type. - */ - @Override - public Color getMinValue() - { - return null; - } - -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +//import java.awt.Color; +import android.graphics.Color; + +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.TypeRegistry; + +/** + * @author awebb + * + */ +public class MetaPrefColor extends MetaPref +{ + /** + * Default value for this MetaPref + */ + @simpl_scalar Color defaultValue; + + public static final ScalarType COLOR_SCALAR_TYPE = TypeRegistry.getScalarType(Color.class); + + public MetaPrefColor() + { + super(COLOR_SCALAR_TYPE); + } + + /** + * Gets the default value of a MetaPref. + * + * @return Default value of MetaPref, or Black if null. + */ + @Override + public Color getDefaultValue() + { + return (Color) ((defaultValue != null) ? defaultValue : Color.BLACK); + } + + /** + * Construct a new instance of the Pref that matches this. + * Use this to fill-in the default value. + * + * @return new Pref instance + */ + @Override + protected Pref getPrefInstance() + { + return new PrefColor(); + } + + /** + * Get max value; returns null for this type. + */ + @Override + public Color getMaxValue() + { + return null; + } + + /** + * Get min value; returns null for this type. + */ + @Override + public Color getMinValue() + { + return null; + } + +} diff --git a/simplPlatformSpecifics/Android/src/ecologylab/appframework/types/prefs/PrefColor.java b/simplAndroidSpecifics/src/ecologylab/appframework/types/prefs/PrefColor.java similarity index 93% rename from simplPlatformSpecifics/Android/src/ecologylab/appframework/types/prefs/PrefColor.java rename to simplAndroidSpecifics/src/ecologylab/appframework/types/prefs/PrefColor.java index b3772e47..8eb21f64 100644 --- a/simplPlatformSpecifics/Android/src/ecologylab/appframework/types/prefs/PrefColor.java +++ b/simplAndroidSpecifics/src/ecologylab/appframework/types/prefs/PrefColor.java @@ -1,71 +1,71 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -//import java.awt.Color; -import android.graphics.Color; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * A preference that is a Color. - * - * @author awebb - * - */ -public class PrefColor extends Pref -{ - @simpl_scalar - Color value; - - public PrefColor() - { - super(); - } - - public PrefColor(Color value) - { - super(); - this.value = value; - } - - public PrefColor(String name, Color value) - { - super(); - this.name = name; - this.value = value; - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#getValue() - */ - @Override - protected Color getValue() - { - return value; - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#setValue(T) - */ - @Override - public void setValue(Color newValue) - { - this.value = newValue; - - prefChanged(); - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#clone() - */ - @Override - public Pref clone() - { - return new PrefColor(this.name, this.value); - } - - public void register(){ - super.register(); - } +/** + * + */ +package ecologylab.appframework.types.prefs; + +//import java.awt.Color; +import android.graphics.Color; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * A preference that is a Color. + * + * @author awebb + * + */ +public class PrefColor extends Pref +{ + @simpl_scalar + Color value; + + public PrefColor() + { + super(); + } + + public PrefColor(Color value) + { + super(); + this.value = value; + } + + public PrefColor(String name, Color value) + { + super(); + this.name = name; + this.value = value; + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#getValue() + */ + @Override + protected Color getValue() + { + return value; + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#setValue(T) + */ + @Override + public void setValue(Color newValue) + { + this.value = newValue; + + prefChanged(); + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#clone() + */ + @Override + public Pref clone() + { + return new PrefColor(this.name, this.value); + } + + public void register(){ + super.register(); + } } \ No newline at end of file diff --git a/simplPlatformSpecifics/Android/src/ecologylab/oodss/distributed/client/BinaryWebSocketClient.java b/simplAndroidSpecifics/src/ecologylab/oodss/distributed/client/BinaryWebSocketClient.java similarity index 96% rename from simplPlatformSpecifics/Android/src/ecologylab/oodss/distributed/client/BinaryWebSocketClient.java rename to simplAndroidSpecifics/src/ecologylab/oodss/distributed/client/BinaryWebSocketClient.java index 029778dd..cecdd69e 100644 --- a/simplPlatformSpecifics/Android/src/ecologylab/oodss/distributed/client/BinaryWebSocketClient.java +++ b/simplAndroidSpecifics/src/ecologylab/oodss/distributed/client/BinaryWebSocketClient.java @@ -1,888 +1,888 @@ -package ecologylab.oodss.distributed.client; - - -import java.io.*; -import java.net.HttpCookie; -import java.net.Socket; -import java.net.URI; -import java.net.UnknownHostException; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import javolution.util.FastList; -import javolution.util.FastMap; -import org.jwebsocket.api.*; -import org.jwebsocket.client.java.ReliabilityOptions; -import org.jwebsocket.client.token.WebSocketTokenClientEvent; -import org.jwebsocket.config.JWebSocketCommonConstants; -import org.jwebsocket.kit.*; -import org.jwebsocket.util.Tools; - -public class BinaryWebSocketClient implements WebSocketClient{ - private static final int RECEIVER_SHUTDOWN_TIMEOUT = 3000; - /** - * WebSocket connection URI - */ - private URI mURI = null; - /** - * list of the listeners registered - */ - private List mListeners = new FastList(); - /** - * TCP socket - */ - private Socket mSocket = null; - /** - * IO streams - */ - private InputStream mIn = null; - private OutputStream mOut = null; - /** - * Data receiver - */ - private WebSocketReceiver mReceiver = null; - /** - * represents the WebSocket status - */ - protected volatile WebSocketStatus mStatus = WebSocketStatus.CLOSED; - private List mSubprotocols; - private WebSocketSubProtocol mNegotiatedSubProtocol; - /** - * - */ - public static String EVENT_OPEN = "open"; - /** - * - */ - public static String EVENT_CLOSE = "close"; - /** - * - */ - public static String DATA_CLOSE_ERROR = "error"; - /** - * - */ - public static String DATA_CLOSE_CLIENT = "client"; - /** - * - */ - public static String DATA_CLOSE_SERVER = "server"; - /** - * - */ - public static String DATA_CLOSE_SHUTDOWN = "shutdown"; - private static final String CR_CLIENT = "Client closed connection"; - private int mVersion = JWebSocketCommonConstants.WS_VERSION_DEFAULT; - private WebSocketEncoding mEncoding = WebSocketEncoding.BINARY; - private ReliabilityOptions mReliabilityOptions = null; - private final ScheduledThreadPoolExecutor mExecutor = new ScheduledThreadPoolExecutor(1); - private final Map mParams = new FastMap(); - private final Object mWriteLock = new Object(); - private String mCloseReason = null; - private ScheduledFuture mReconnectorTask = null; - private Boolean mIsReconnecting = false; - private final Object mReconnectLock = new Object(); - private Headers mHeaders = null; - private List mCookies = new ArrayList(); - - /** - * Base constructor - */ - public BinaryWebSocketClient() { - } - - public void setStatus(WebSocketStatus aStatus) throws Exception { - if (aStatus.equals(WebSocketStatus.AUTHENTICATED)) { - this.mStatus = aStatus; - } else { - throw new Exception("The value '" + aStatus.name() - + "' cannot be assigned. Restricted to internal usage only!"); - } - } - - /** - * Constructor including reliability options - */ - public BinaryWebSocketClient(ReliabilityOptions aReliabilityOptions) { - mReliabilityOptions = aReliabilityOptions; - } - - /** - * - * @param aKey - * @param aDefault - * @return - */ - public Object getParam(String aKey, Object aDefault) { - Object lValue = mParams.get(aKey); - if (null == lValue) { - lValue = aDefault; - } - return lValue; - } - - /** - * - * @param aKey - * @return - */ - public Object getParam(String aKey) { - return mParams.get(aKey); - } - - /** - * - * @param aKey - * @param aValue - */ - public void setParam(String aKey, Object aValue) { - mParams.put(aKey, aValue); - } - - /** - * {@inheritDoc} - * - * @param aURI - */ - public void open(String aURI) throws WebSocketException { - open(JWebSocketCommonConstants.WS_VERSION_DEFAULT, aURI); - } - - /** - * Make a sub protocol string for Sec-WebSocket-Protocol header. The result - * is something like this: - *
-	 * org.jwebsocket.json org.websocket.text org.jwebsocket.binary
-	 * 
- * - * @return sub protocol list in one string - */ - private String generateSubProtocolsHeaderValue() { - if (mSubprotocols == null || mSubprotocols.size() <= 0) { - return JWebSocketCommonConstants.WS_SUBPROT_DEFAULT; - } else { - StringBuilder lBuff = new StringBuilder(); - for (WebSocketSubProtocol lProt : mSubprotocols) { - lBuff.append(lProt.getSubProt()).append(' '); - } - return lBuff.toString().trim(); - } - } - - /** - * - * @param aVersion - * @param aURI - * @throws WebSocketException - */ - public void open(int aVersion, String aURI) { - String lSubProtocols = generateSubProtocolsHeaderValue(); - open(aVersion, aURI, lSubProtocols); - } - - /** - * - * @param aVersion - * @param aURI - * @param aSubProtocols - * @throws WebSocketException - */ - public void open(int aVersion, String aURI, String aSubProtocols) { - try { - mAbortReconnect(); - - // set default close reason in case - // connection could not be established. - mCloseReason = "Connection could not be established."; - - mVersion = aVersion; - mURI = new URI(aURI); - // the WebSocket Handshake here generates the initial client side Handshake only - WebSocketHandshake lHandshake = new WebSocketHandshake(mVersion, mURI, aSubProtocols); - // close current socket if still connected - // to avoid open connections on server - if (mSocket != null && mSocket.isConnected()) { - mSocket.close(); - } - mSocket = createSocket(); - // don't gather packages here, reduce latency - mSocket.setTcpNoDelay(true); - mIn = mSocket.getInputStream(); - mOut = mSocket.getOutputStream(); - - // pass session cookie, if already was set for this client instance - byte[] lBA; - List lTempCookies = new ArrayList(); - if (null != mCookies) { - HttpCookie lCookie; - for (int lIndex = 0; lIndex < mCookies.size(); lIndex++) { - lCookie = mCookies.get(lIndex); - boolean lValid = Tools.isCookieValid(mURI, lCookie); - if (lValid) { - // Cookie is valid - lTempCookies.add(lCookie); - } - } - } - lBA = lHandshake.generateC2SRequest(lTempCookies); - mOut.write(lBA); - - mStatus = WebSocketStatus.CONNECTING; - - mHeaders = new Headers(); - try { - mHeaders.readFromStream(aVersion, mIn); - } catch (Exception lEx) { - // ignore exception here, will be processed afterwards - } - - // registering new cookies from the server response - String lSetCookie = mHeaders.getField("Set-Cookie"); - if (null != lSetCookie) { - List lCookies = HttpCookie.parse(lSetCookie); - if (mCookies.isEmpty()) { - mCookies.addAll(lCookies); - } else { - for (HttpCookie lCookie : lCookies) { - for (int lIndex = 0; lIndex < mCookies.size(); lIndex++) { - if (null == mCookies.get(lIndex).getDomain() - || HttpCookie.domainMatches(mCookies.get(lIndex).getDomain(), mURI.getHost()) - && (null == lCookie.getPath() - || (null != mURI.getPath() - && mURI.getPath().startsWith(lCookie.getPath())))) { - mCookies.set(lIndex, lCookie); - } - } - if (!mCookies.contains(lCookie)) { - mCookies.add(lCookie); - } - } - } - } - - if (!mHeaders.isValid()) { - WebSocketClientEvent lEvent = - new WebSocketBaseClientEvent(this, EVENT_CLOSE, "Handshake rejected."); - notifyClosed(lEvent); - mCheckReconnect(lEvent); - return; - } - - // parse negotiated sub protocol - String lProtocol = mHeaders.getField(Headers.SEC_WEBSOCKET_PROTOCOL); - if (lProtocol != null) { - mNegotiatedSubProtocol = new WebSocketSubProtocol(lProtocol, mEncoding); - } else { - mNegotiatedSubProtocol = new WebSocketSubProtocol( - JWebSocketCommonConstants.WS_SUBPROT_BINARY, - WebSocketEncoding.BINARY); - - } - // create new thread to receive the data from the new client - mReceiver = new WebSocketReceiver(this, mIn); - // and start the receiver thread for the port - mReceiver.start(); - // now set official status, may listeners ask for that - mStatus = WebSocketStatus.OPEN; - // and finally notify listeners for OnOpen event - WebSocketClientEvent lEvent = - new WebSocketBaseClientEvent(this, EVENT_OPEN, ""); - // notify listeners that client has opened. - notifyOpened(lEvent); - - // reset close reason to be specified by next reason - mCloseReason = null; - } catch (Exception lEx) { - WebSocketClientEvent lEvent = - new WebSocketBaseClientEvent(this, EVENT_CLOSE, mCloseReason); - notifyClosed(lEvent); - mCheckReconnect(lEvent); - } - } - - private void sendInTransaction(byte[] aData) throws WebSocketException { - if (isHixie()) { - sendInternal(aData); - } else { - WebSocketPacket lPacket = new RawPacket(aData); - lPacket.setFrameType( - WebSocketProtocolAbstraction.encodingToFrameType( - mNegotiatedSubProtocol.getEncoding())); - sendInternal( - WebSocketProtocolAbstraction.rawToProtocolPacket( - mVersion, lPacket)); - } - } - - public void send(byte[] aData) throws WebSocketException { - synchronized (mWriteLock) { - sendInTransaction(aData); - } - } - - /** - * {@inheritDoc} - */ - public void send(String aData, String aEncoding) throws WebSocketException { - synchronized (mWriteLock) { - byte[] lData; - try { - lData = aData.getBytes(aEncoding); - } catch (UnsupportedEncodingException lEx) { - throw new WebSocketException( - "Encoding exception while sending the data:" - + lEx.getMessage(), lEx); - } - send(lData); - } - } - - /** - * {@inheritDoc} - * - * @param aDataPacket - */ - public void send(WebSocketPacket aDataPacket) throws WebSocketException { - synchronized (mWriteLock) { - if (isHixie()) { - sendInternal(aDataPacket.getByteArray()); - } else { - sendInternal(WebSocketProtocolAbstraction.rawToProtocolPacket(mVersion, aDataPacket)); - } - } - } - - private void sendInternal(byte[] aData) throws WebSocketException { - if (!mStatus.isWritable()) { - throw new WebSocketException("Error while sending binary data: not connected"); - } - try { - if (isHixie()) { - if (WebSocketEncoding.BINARY.equals(mNegotiatedSubProtocol.getEncoding())) { - mOut.write(0x80); - // what if frame is longer than 255 characters (8bit?) Refer to IETF spec! - // won't fix since hixie is far outdated! - mOut.write(aData.length); - mOut.write(aData); - } else { - mOut.write(0x00); - mOut.write(aData); - mOut.write(0xff); - } - } else { - mOut.write(aData); - } - mOut.flush(); - } catch (IOException lEx) { - terminateReceiverThread(); - throw new WebSocketException("Error while sending socket data: ", lEx); - } - } - - private void terminateReceiverThread() throws WebSocketException { - mReceiver.quit(); - try { - mReceiver.join(RECEIVER_SHUTDOWN_TIMEOUT); - } catch (InterruptedException lEx) { - throw new WebSocketException( - "Receiver thread did not stop within " - + RECEIVER_SHUTDOWN_TIMEOUT + " ms", lEx); - } - mReceiver = null; - } - - private void setCloseReason(String aCloseReason) { - if (null == mCloseReason) { - mCloseReason = aCloseReason; - } - } - - public synchronized void close() { - // on an explicit close operation ... - // cancel all potential re-connection tasks. - mAbortReconnect(); - if (null != mReceiver) { - mReceiver.quit(); - } - - if (!mStatus.isWritable()) { - return; - } - setCloseReason(CR_CLIENT); - try { - sendCloseHandshake(); - } catch (Exception lEx) { - // ignore that, connection is about to be terminated - } - try { - // stopping the receiver thread stops the entire client - terminateReceiverThread(); - } catch (Exception lEx) { - // ignore that, connection is about to be terminated - } - } - - private void sendCloseHandshake() throws WebSocketException { - if (!mStatus.isClosable()) { - throw new WebSocketException("Error while sending close handshake: not connected"); - } - synchronized (mWriteLock) { - try { - if (isHixie()) { - // old hixie close handshake - mOut.write(0xff00); - mOut.flush(); - } else { - WebSocketPacket lPacket = new RawPacket(WebSocketFrameType.CLOSE, "BYE"); - send(lPacket); - } - } catch (IOException lIOEx) { - throw new WebSocketException("Error while sending close handshake", lIOEx); - } - } - } - - private Socket createSocket() throws WebSocketException { - String lScheme = mURI.getScheme(); - String lHost = mURI.getHost(); - int lPort = mURI.getPort(); - - mSocket = null; - - if (lScheme != null && lScheme.equals("ws")) { - if (lPort == -1) { - lPort = 80; - } - try { - mSocket = new Socket(lHost, lPort); - } catch (UnknownHostException lUHEx) { - throw new WebSocketException("Unknown host: " + lHost, - WebSocketExceptionType.UNKNOWN_HOST, lUHEx); - } catch (IOException lIOEx) { - throw new WebSocketException("Error while creating socket to " + mURI, - WebSocketExceptionType.UNABLE_TO_CONNECT, lIOEx); - } - } else if (lScheme != null && lScheme.equals("wss")) { - if (lPort == -1) { - lPort = 443; - } - try { - try { - // TODO: Make acceptance of unsigned certificates optional! - // This methodology is used to accept unsigned certficates - // on the SSL server. Be careful with this in production environments! - - // Create a trust manager to accept unsigned certificates - TrustManager[] lTrustManager = new TrustManager[]{ - new X509TrustManager() { - - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return null; - } - - public void checkClientTrusted( - java.security.cert.X509Certificate[] aCerts, String aAuthType) { - } - - public void checkServerTrusted( - java.security.cert.X509Certificate[] aCerts, String aAuthType) { - } - } - }; - // Use this trustmanager to not reject unsigned certificates - SSLContext lSSLContext = SSLContext.getInstance("TLS"); - lSSLContext.init(null, lTrustManager, new java.security.SecureRandom()); - mSocket = (SSLSocket) lSSLContext.getSocketFactory().createSocket(lHost, lPort); - } catch (NoSuchAlgorithmException lNSAEx) { - throw new RuntimeException("Unable to initialize SSL context", lNSAEx); - } catch (KeyManagementException lKMEx) { - throw new RuntimeException("Unable to initialize SSL context", lKMEx); - } - } catch (UnknownHostException lUHEx) { - throw new WebSocketException("Unknown host: " + lHost, - WebSocketExceptionType.UNKNOWN_HOST, lUHEx); - } catch (IOException lIOEx) { - throw new WebSocketException("Error while creating secure socket to " + mURI, - WebSocketExceptionType.UNABLE_TO_CONNECT_SSL, lIOEx); - } catch (Exception lEx) { - throw new WebSocketException(lEx.getClass().getSimpleName() + " while creating secure socket to " + mURI, lEx); - } - } else { - throw new WebSocketException("Unsupported protocol: " + lScheme, - WebSocketExceptionType.PROTOCOL_NOT_SUPPORTED); - } - - return mSocket; - } - - /** - * {@inheritDoc } - */ - public boolean isConnected() { - return mStatus.isConnected(); - } - - public WebSocketStatus getStatus() { - return mStatus; - } - - /** - * {@inheritDoc } - * - * @return - */ - public WebSocketStatus getConnectionStatus() { - return mStatus; - } - - /** - * @return the client socket - */ - public Socket getConnectionSocket() { - return mSocket; - } - - /** - * {@inheritDoc} - */ - public void addListener(WebSocketClientListener aListener) { - mListeners.add(aListener); - } - - /** - * {@inheritDoc} - */ - public void removeListener(WebSocketClientListener aListener) { - mListeners.remove(aListener); - } - - /** - * {@inheritDoc} - */ - public List getListeners() { - return Collections.unmodifiableList(mListeners); - } - - /** - * {@inheritDoc} - */ - public void notifyOpened(WebSocketClientEvent aEvent) { - for (WebSocketClientListener lListener : getListeners()) { - lListener.processOpened(aEvent); - } - } - - /** - * {@inheritDoc} - */ - public void notifyPacket(WebSocketClientEvent aEvent, WebSocketPacket aPacket) { - for (WebSocketClientListener lListener : getListeners()) { - lListener.processPacket(aEvent, aPacket); - } - } - - /** - * {@inheritDoc} - */ - public void notifyReconnecting(WebSocketClientEvent aEvent) { - for (WebSocketClientListener lListener : getListeners()) { - lListener.processReconnecting(aEvent); - } - } - - /** - * @return the mReliabilityOptions - */ - public ReliabilityOptions getReliabilityOptions() { - return mReliabilityOptions; - } - - /** - * @param mReliabilityOptions the mReliabilityOptions to set - */ - public void setReliabilityOptions(ReliabilityOptions mReliabilityOptions) { - this.mReliabilityOptions = mReliabilityOptions; - } - /* - * class ReOpener implements Runnable { - * - * private WebSocketClientEvent mEvent; - * - * public ReOpener(WebSocketClientEvent aEvent) { mEvent = aEvent; } - * - * @Override public void run() { notifyReconnecting(mEvent); try { - * open(mURI.toString()); } catch (WebSocketException ex) { // TODO: process - * potential exception here! } } } - */ - - /** - * @return the mHeaders - */ - public Headers getHeaders() { - return mHeaders; - } - - class ReOpener implements Runnable { - - private WebSocketClientEvent mEvent; - - public ReOpener(WebSocketClientEvent aEvent) { - mEvent = aEvent; - } - - public void run() { - mIsReconnecting = false; - notifyReconnecting(mEvent); - try { - open(mURI.toString()); - // did we configure reliability options? - /* - * if (mReliabilityOptions != null && - * mReliabilityOptions.getReconnectDelay() > 0) { - * mExecutor.schedule( new ReOpener(aEvent), - * mReliabilityOptions.getReconnectDelay(), - * TimeUnit.MILLISECONDS); } - */ - } catch (Exception lEx) { - WebSocketClientEvent lEvent = - new WebSocketBaseClientEvent(mEvent.getClient(), EVENT_CLOSE, - lEx.getClass().getSimpleName() + ": " - + lEx.getMessage()); - notifyClosed(lEvent); - } - } - } - - private void mAbortReconnect() { - synchronized (mReconnectLock) { - // cancel running re-connect task - if (null != mReconnectorTask) { - mReconnectorTask.cancel(true); - } - // reset internal re-connection flag - mIsReconnecting = false; - mReconnectorTask = null; - // clean up all potentially old references to inactive tasks - mExecutor.purge(); - } - } - - private void mCheckReconnect(WebSocketClientEvent aEvent) { - synchronized (mReconnectLock) { - // first, purge all potentially old references to other tasks - mExecutor.purge(); - // did we configure reliability options? - // and is there now re-connection task already active? - if (mReliabilityOptions != null - && mReliabilityOptions.getReconnectDelay() > 0 - && !mIsReconnecting) { - // schedule a re-connect action after the re-connect delay - mIsReconnecting = true; - mReconnectorTask = mExecutor.schedule( - new ReOpener(aEvent), - mReliabilityOptions.getReconnectDelay(), - TimeUnit.MILLISECONDS); - } - } - } - - /** - * {@inheritDoc} - */ - public void notifyClosed(WebSocketClientEvent aEvent) { - for (WebSocketClientListener lListener : getListeners()) { - lListener.processClosed(aEvent); - } - } - - public void addSubProtocol(WebSocketSubProtocol aSubProt) { - if (mSubprotocols == null) { - mSubprotocols = new ArrayList(3); - } - mSubprotocols.add(aSubProt); - } - - public String getNegotiatedSubProtocol() { - return mNegotiatedSubProtocol == null ? null : mNegotiatedSubProtocol.getSubProt(); - } - - public WebSocketEncoding getNegotiatedEncoding() { - return mNegotiatedSubProtocol == null ? null : mNegotiatedSubProtocol.getEncoding(); - } - - public void setVersion(int aVersion) { - this.mVersion = aVersion; - } - - private boolean isHixie() { - return WebSocketProtocolAbstraction.isHixieVersion(mVersion); - } - - class WebSocketReceiver extends Thread { - - private WebSocketClient mClient = null; - private InputStream mIS = null; - private volatile boolean mIsRunning = false; - - public WebSocketReceiver(WebSocketClient aClient, InputStream aInput) { - mClient = aClient; - mIS = aInput; - } - - @Override - public void run() { - Thread.currentThread().setName("jWebSocket-Client " + getId()); - - mIsRunning = true; - - // the hixie and hybi processors handle potential exceptions - if (isHixie()) { - processHixie(); - } else { - processHybi(); - } - - // set status AFTER close frame was sent, otherwise sending - // close frame leads to an exception. - mStatus = WebSocketStatus.CLOSING; - String lExMsg = ""; - try { - // shutdown methods are not implemented for SSL sockets - if (!(mSocket instanceof SSLSocket)) { - if (!mSocket.isOutputShutdown()) { - mSocket.shutdownInput(); - } - } - } catch (IOException lIOEx) { - lExMsg += "Shutdown input: " + lIOEx.getMessage() + ", "; - } - try { - // shutdown methods are not implemented for SSL sockets - if (!(mSocket instanceof SSLSocket)) { - if (!mSocket.isOutputShutdown()) { - mSocket.shutdownOutput(); - } - } - } catch (IOException lIOEx) { - lExMsg += "Shutdown output: " + lIOEx.getMessage() + ", "; - } - try { - if (!mSocket.isClosed()) { - mSocket.close(); - } - } catch (IOException lIOEx) { - lExMsg += "Socket close: " + lIOEx.getMessage() + ", "; - } - - // now the connection is really closed - // set the status accordingly - mStatus = WebSocketStatus.CLOSED; - - WebSocketClientEvent lEvent = - new WebSocketBaseClientEvent(mClient, EVENT_CLOSE, mCloseReason); - // notify listeners that client has closed - notifyClosed(lEvent); - - quit(); - - if (!CR_CLIENT.equals(mCloseReason)) { - mCheckReconnect(lEvent); - } - } - - private void processHixie() { - boolean lFrameStart = false; - ByteArrayOutputStream lBuff = new ByteArrayOutputStream(); - while (mIsRunning) { - try { - int lB = mIS.read(); - // TODO: support binary frames - if (lB == 0x00) { - lFrameStart = true; - } else if (lB == 0xff && lFrameStart == true) { - lFrameStart = false; - - WebSocketClientEvent lWSCE = new WebSocketTokenClientEvent(mClient, null, null); - RawPacket lPacket = new RawPacket(lBuff.toByteArray()); - - lBuff.reset(); - notifyPacket(lWSCE, lPacket); - } else if (lFrameStart == true) { - lBuff.write(lB); - } else if (lB == -1) { - setCloseReason("Inbound stream terminated"); - mIsRunning = false; - } - } catch (Exception lEx) { - mIsRunning = false; - setCloseReason(lEx.getClass().getName() + " in hybi processor: " + lEx.getMessage()); - } - } - } - - private void processHybi() { - WebSocketClientEvent lWSCE; - WebSocketFrameType lFrameType; - - while (mIsRunning) { - try { - WebSocketPacket lPacket = WebSocketProtocolAbstraction.protocolToRawPacket(mVersion, mIS); - lFrameType = (lPacket != null ? lPacket.getFrameType() : WebSocketFrameType.INVALID); - if (null == lFrameType) { - if (mIsRunning) { - setCloseReason("Connection broken"); - } else { - setCloseReason("Client terminated"); - } - mIsRunning = false; - } else if (WebSocketFrameType.INVALID == lFrameType) { - mIsRunning = false; - setCloseReason("Invalid hybi frame type detected"); - } else if (WebSocketFrameType.CLOSE == lFrameType) { - mIsRunning = false; - setCloseReason("Server closed connection"); - } else if (WebSocketFrameType.PING == lFrameType) { - WebSocketPacket lPong = new RawPacket( - WebSocketFrameType.PONG, ""); - send(lPong); - } else if (WebSocketFrameType.PONG == lFrameType) { - // TODO: need to process connection management here! - } else if (WebSocketFrameType.TEXT == lFrameType) { - lWSCE = new WebSocketTokenClientEvent(mClient, null, null); - notifyPacket(lWSCE, lPacket); - } else if (WebSocketFrameType.BINARY == lFrameType) { - lWSCE = new WebSocketTokenClientEvent(mClient, null, null); - notifyPacket(lWSCE, lPacket); - } - } catch (Exception lEx) { - mIsRunning = false; - setCloseReason(lEx.getClass().getName() + " in hybi processor: " + lEx.getMessage()); - } - } - } - - public void quit() { - // ensure that reader loops are not continued - mIsRunning = false; - try { - mIS.close(); - } catch (IOException ex) { - // just to force client reader to stop - } - } - - public boolean isRunning() { - return mIsRunning; - } - } -} +package ecologylab.oodss.distributed.client; + + +import java.io.*; +import java.net.HttpCookie; +import java.net.Socket; +import java.net.URI; +import java.net.UnknownHostException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import javolution.util.FastList; +import javolution.util.FastMap; +import org.jwebsocket.api.*; +import org.jwebsocket.client.java.ReliabilityOptions; +import org.jwebsocket.client.token.WebSocketTokenClientEvent; +import org.jwebsocket.config.JWebSocketCommonConstants; +import org.jwebsocket.kit.*; +import org.jwebsocket.util.Tools; + +public class BinaryWebSocketClient implements WebSocketClient{ + private static final int RECEIVER_SHUTDOWN_TIMEOUT = 3000; + /** + * WebSocket connection URI + */ + private URI mURI = null; + /** + * list of the listeners registered + */ + private List mListeners = new FastList(); + /** + * TCP socket + */ + private Socket mSocket = null; + /** + * IO streams + */ + private InputStream mIn = null; + private OutputStream mOut = null; + /** + * Data receiver + */ + private WebSocketReceiver mReceiver = null; + /** + * represents the WebSocket status + */ + protected volatile WebSocketStatus mStatus = WebSocketStatus.CLOSED; + private List mSubprotocols; + private WebSocketSubProtocol mNegotiatedSubProtocol; + /** + * + */ + public static String EVENT_OPEN = "open"; + /** + * + */ + public static String EVENT_CLOSE = "close"; + /** + * + */ + public static String DATA_CLOSE_ERROR = "error"; + /** + * + */ + public static String DATA_CLOSE_CLIENT = "client"; + /** + * + */ + public static String DATA_CLOSE_SERVER = "server"; + /** + * + */ + public static String DATA_CLOSE_SHUTDOWN = "shutdown"; + private static final String CR_CLIENT = "Client closed connection"; + private int mVersion = JWebSocketCommonConstants.WS_VERSION_DEFAULT; + private WebSocketEncoding mEncoding = WebSocketEncoding.BINARY; + private ReliabilityOptions mReliabilityOptions = null; + private final ScheduledThreadPoolExecutor mExecutor = new ScheduledThreadPoolExecutor(1); + private final Map mParams = new FastMap(); + private final Object mWriteLock = new Object(); + private String mCloseReason = null; + private ScheduledFuture mReconnectorTask = null; + private Boolean mIsReconnecting = false; + private final Object mReconnectLock = new Object(); + private Headers mHeaders = null; + private List mCookies = new ArrayList(); + + /** + * Base constructor + */ + public BinaryWebSocketClient() { + } + + public void setStatus(WebSocketStatus aStatus) throws Exception { + if (aStatus.equals(WebSocketStatus.AUTHENTICATED)) { + this.mStatus = aStatus; + } else { + throw new Exception("The value '" + aStatus.name() + + "' cannot be assigned. Restricted to internal usage only!"); + } + } + + /** + * Constructor including reliability options + */ + public BinaryWebSocketClient(ReliabilityOptions aReliabilityOptions) { + mReliabilityOptions = aReliabilityOptions; + } + + /** + * + * @param aKey + * @param aDefault + * @return + */ + public Object getParam(String aKey, Object aDefault) { + Object lValue = mParams.get(aKey); + if (null == lValue) { + lValue = aDefault; + } + return lValue; + } + + /** + * + * @param aKey + * @return + */ + public Object getParam(String aKey) { + return mParams.get(aKey); + } + + /** + * + * @param aKey + * @param aValue + */ + public void setParam(String aKey, Object aValue) { + mParams.put(aKey, aValue); + } + + /** + * {@inheritDoc} + * + * @param aURI + */ + public void open(String aURI) throws WebSocketException { + open(JWebSocketCommonConstants.WS_VERSION_DEFAULT, aURI); + } + + /** + * Make a sub protocol string for Sec-WebSocket-Protocol header. The result + * is something like this: + *
+	 * org.jwebsocket.json org.websocket.text org.jwebsocket.binary
+	 * 
+ * + * @return sub protocol list in one string + */ + private String generateSubProtocolsHeaderValue() { + if (mSubprotocols == null || mSubprotocols.size() <= 0) { + return JWebSocketCommonConstants.WS_SUBPROT_DEFAULT; + } else { + StringBuilder lBuff = new StringBuilder(); + for (WebSocketSubProtocol lProt : mSubprotocols) { + lBuff.append(lProt.getSubProt()).append(' '); + } + return lBuff.toString().trim(); + } + } + + /** + * + * @param aVersion + * @param aURI + * @throws WebSocketException + */ + public void open(int aVersion, String aURI) { + String lSubProtocols = generateSubProtocolsHeaderValue(); + open(aVersion, aURI, lSubProtocols); + } + + /** + * + * @param aVersion + * @param aURI + * @param aSubProtocols + * @throws WebSocketException + */ + public void open(int aVersion, String aURI, String aSubProtocols) { + try { + mAbortReconnect(); + + // set default close reason in case + // connection could not be established. + mCloseReason = "Connection could not be established."; + + mVersion = aVersion; + mURI = new URI(aURI); + // the WebSocket Handshake here generates the initial client side Handshake only + WebSocketHandshake lHandshake = new WebSocketHandshake(mVersion, mURI, aSubProtocols); + // close current socket if still connected + // to avoid open connections on server + if (mSocket != null && mSocket.isConnected()) { + mSocket.close(); + } + mSocket = createSocket(); + // don't gather packages here, reduce latency + mSocket.setTcpNoDelay(true); + mIn = mSocket.getInputStream(); + mOut = mSocket.getOutputStream(); + + // pass session cookie, if already was set for this client instance + byte[] lBA; + List lTempCookies = new ArrayList(); + if (null != mCookies) { + HttpCookie lCookie; + for (int lIndex = 0; lIndex < mCookies.size(); lIndex++) { + lCookie = mCookies.get(lIndex); + boolean lValid = Tools.isCookieValid(mURI, lCookie); + if (lValid) { + // Cookie is valid + lTempCookies.add(lCookie); + } + } + } + lBA = lHandshake.generateC2SRequest(lTempCookies); + mOut.write(lBA); + + mStatus = WebSocketStatus.CONNECTING; + + mHeaders = new Headers(); + try { + mHeaders.readFromStream(aVersion, mIn); + } catch (Exception lEx) { + // ignore exception here, will be processed afterwards + } + + // registering new cookies from the server response + String lSetCookie = mHeaders.getField("Set-Cookie"); + if (null != lSetCookie) { + List lCookies = HttpCookie.parse(lSetCookie); + if (mCookies.isEmpty()) { + mCookies.addAll(lCookies); + } else { + for (HttpCookie lCookie : lCookies) { + for (int lIndex = 0; lIndex < mCookies.size(); lIndex++) { + if (null == mCookies.get(lIndex).getDomain() + || HttpCookie.domainMatches(mCookies.get(lIndex).getDomain(), mURI.getHost()) + && (null == lCookie.getPath() + || (null != mURI.getPath() + && mURI.getPath().startsWith(lCookie.getPath())))) { + mCookies.set(lIndex, lCookie); + } + } + if (!mCookies.contains(lCookie)) { + mCookies.add(lCookie); + } + } + } + } + + if (!mHeaders.isValid()) { + WebSocketClientEvent lEvent = + new WebSocketBaseClientEvent(this, EVENT_CLOSE, "Handshake rejected."); + notifyClosed(lEvent); + mCheckReconnect(lEvent); + return; + } + + // parse negotiated sub protocol + String lProtocol = mHeaders.getField(Headers.SEC_WEBSOCKET_PROTOCOL); + if (lProtocol != null) { + mNegotiatedSubProtocol = new WebSocketSubProtocol(lProtocol, mEncoding); + } else { + mNegotiatedSubProtocol = new WebSocketSubProtocol( + JWebSocketCommonConstants.WS_SUBPROT_BINARY, + WebSocketEncoding.BINARY); + + } + // create new thread to receive the data from the new client + mReceiver = new WebSocketReceiver(this, mIn); + // and start the receiver thread for the port + mReceiver.start(); + // now set official status, may listeners ask for that + mStatus = WebSocketStatus.OPEN; + // and finally notify listeners for OnOpen event + WebSocketClientEvent lEvent = + new WebSocketBaseClientEvent(this, EVENT_OPEN, ""); + // notify listeners that client has opened. + notifyOpened(lEvent); + + // reset close reason to be specified by next reason + mCloseReason = null; + } catch (Exception lEx) { + WebSocketClientEvent lEvent = + new WebSocketBaseClientEvent(this, EVENT_CLOSE, mCloseReason); + notifyClosed(lEvent); + mCheckReconnect(lEvent); + } + } + + private void sendInTransaction(byte[] aData) throws WebSocketException { + if (isHixie()) { + sendInternal(aData); + } else { + WebSocketPacket lPacket = new RawPacket(aData); + lPacket.setFrameType( + WebSocketProtocolAbstraction.encodingToFrameType( + mNegotiatedSubProtocol.getEncoding())); + sendInternal( + WebSocketProtocolAbstraction.rawToProtocolPacket( + mVersion, lPacket)); + } + } + + public void send(byte[] aData) throws WebSocketException { + synchronized (mWriteLock) { + sendInTransaction(aData); + } + } + + /** + * {@inheritDoc} + */ + public void send(String aData, String aEncoding) throws WebSocketException { + synchronized (mWriteLock) { + byte[] lData; + try { + lData = aData.getBytes(aEncoding); + } catch (UnsupportedEncodingException lEx) { + throw new WebSocketException( + "Encoding exception while sending the data:" + + lEx.getMessage(), lEx); + } + send(lData); + } + } + + /** + * {@inheritDoc} + * + * @param aDataPacket + */ + public void send(WebSocketPacket aDataPacket) throws WebSocketException { + synchronized (mWriteLock) { + if (isHixie()) { + sendInternal(aDataPacket.getByteArray()); + } else { + sendInternal(WebSocketProtocolAbstraction.rawToProtocolPacket(mVersion, aDataPacket)); + } + } + } + + private void sendInternal(byte[] aData) throws WebSocketException { + if (!mStatus.isWritable()) { + throw new WebSocketException("Error while sending binary data: not connected"); + } + try { + if (isHixie()) { + if (WebSocketEncoding.BINARY.equals(mNegotiatedSubProtocol.getEncoding())) { + mOut.write(0x80); + // what if frame is longer than 255 characters (8bit?) Refer to IETF spec! + // won't fix since hixie is far outdated! + mOut.write(aData.length); + mOut.write(aData); + } else { + mOut.write(0x00); + mOut.write(aData); + mOut.write(0xff); + } + } else { + mOut.write(aData); + } + mOut.flush(); + } catch (IOException lEx) { + terminateReceiverThread(); + throw new WebSocketException("Error while sending socket data: ", lEx); + } + } + + private void terminateReceiverThread() throws WebSocketException { + mReceiver.quit(); + try { + mReceiver.join(RECEIVER_SHUTDOWN_TIMEOUT); + } catch (InterruptedException lEx) { + throw new WebSocketException( + "Receiver thread did not stop within " + + RECEIVER_SHUTDOWN_TIMEOUT + " ms", lEx); + } + mReceiver = null; + } + + private void setCloseReason(String aCloseReason) { + if (null == mCloseReason) { + mCloseReason = aCloseReason; + } + } + + public synchronized void close() { + // on an explicit close operation ... + // cancel all potential re-connection tasks. + mAbortReconnect(); + if (null != mReceiver) { + mReceiver.quit(); + } + + if (!mStatus.isWritable()) { + return; + } + setCloseReason(CR_CLIENT); + try { + sendCloseHandshake(); + } catch (Exception lEx) { + // ignore that, connection is about to be terminated + } + try { + // stopping the receiver thread stops the entire client + terminateReceiverThread(); + } catch (Exception lEx) { + // ignore that, connection is about to be terminated + } + } + + private void sendCloseHandshake() throws WebSocketException { + if (!mStatus.isClosable()) { + throw new WebSocketException("Error while sending close handshake: not connected"); + } + synchronized (mWriteLock) { + try { + if (isHixie()) { + // old hixie close handshake + mOut.write(0xff00); + mOut.flush(); + } else { + WebSocketPacket lPacket = new RawPacket(WebSocketFrameType.CLOSE, "BYE"); + send(lPacket); + } + } catch (IOException lIOEx) { + throw new WebSocketException("Error while sending close handshake", lIOEx); + } + } + } + + private Socket createSocket() throws WebSocketException { + String lScheme = mURI.getScheme(); + String lHost = mURI.getHost(); + int lPort = mURI.getPort(); + + mSocket = null; + + if (lScheme != null && lScheme.equals("ws")) { + if (lPort == -1) { + lPort = 80; + } + try { + mSocket = new Socket(lHost, lPort); + } catch (UnknownHostException lUHEx) { + throw new WebSocketException("Unknown host: " + lHost, + WebSocketExceptionType.UNKNOWN_HOST, lUHEx); + } catch (IOException lIOEx) { + throw new WebSocketException("Error while creating socket to " + mURI, + WebSocketExceptionType.UNABLE_TO_CONNECT, lIOEx); + } + } else if (lScheme != null && lScheme.equals("wss")) { + if (lPort == -1) { + lPort = 443; + } + try { + try { + // TODO: Make acceptance of unsigned certificates optional! + // This methodology is used to accept unsigned certficates + // on the SSL server. Be careful with this in production environments! + + // Create a trust manager to accept unsigned certificates + TrustManager[] lTrustManager = new TrustManager[]{ + new X509TrustManager() { + + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted( + java.security.cert.X509Certificate[] aCerts, String aAuthType) { + } + + public void checkServerTrusted( + java.security.cert.X509Certificate[] aCerts, String aAuthType) { + } + } + }; + // Use this trustmanager to not reject unsigned certificates + SSLContext lSSLContext = SSLContext.getInstance("TLS"); + lSSLContext.init(null, lTrustManager, new java.security.SecureRandom()); + mSocket = (SSLSocket) lSSLContext.getSocketFactory().createSocket(lHost, lPort); + } catch (NoSuchAlgorithmException lNSAEx) { + throw new RuntimeException("Unable to initialize SSL context", lNSAEx); + } catch (KeyManagementException lKMEx) { + throw new RuntimeException("Unable to initialize SSL context", lKMEx); + } + } catch (UnknownHostException lUHEx) { + throw new WebSocketException("Unknown host: " + lHost, + WebSocketExceptionType.UNKNOWN_HOST, lUHEx); + } catch (IOException lIOEx) { + throw new WebSocketException("Error while creating secure socket to " + mURI, + WebSocketExceptionType.UNABLE_TO_CONNECT_SSL, lIOEx); + } catch (Exception lEx) { + throw new WebSocketException(lEx.getClass().getSimpleName() + " while creating secure socket to " + mURI, lEx); + } + } else { + throw new WebSocketException("Unsupported protocol: " + lScheme, + WebSocketExceptionType.PROTOCOL_NOT_SUPPORTED); + } + + return mSocket; + } + + /** + * {@inheritDoc } + */ + public boolean isConnected() { + return mStatus.isConnected(); + } + + public WebSocketStatus getStatus() { + return mStatus; + } + + /** + * {@inheritDoc } + * + * @return + */ + public WebSocketStatus getConnectionStatus() { + return mStatus; + } + + /** + * @return the client socket + */ + public Socket getConnectionSocket() { + return mSocket; + } + + /** + * {@inheritDoc} + */ + public void addListener(WebSocketClientListener aListener) { + mListeners.add(aListener); + } + + /** + * {@inheritDoc} + */ + public void removeListener(WebSocketClientListener aListener) { + mListeners.remove(aListener); + } + + /** + * {@inheritDoc} + */ + public List getListeners() { + return Collections.unmodifiableList(mListeners); + } + + /** + * {@inheritDoc} + */ + public void notifyOpened(WebSocketClientEvent aEvent) { + for (WebSocketClientListener lListener : getListeners()) { + lListener.processOpened(aEvent); + } + } + + /** + * {@inheritDoc} + */ + public void notifyPacket(WebSocketClientEvent aEvent, WebSocketPacket aPacket) { + for (WebSocketClientListener lListener : getListeners()) { + lListener.processPacket(aEvent, aPacket); + } + } + + /** + * {@inheritDoc} + */ + public void notifyReconnecting(WebSocketClientEvent aEvent) { + for (WebSocketClientListener lListener : getListeners()) { + lListener.processReconnecting(aEvent); + } + } + + /** + * @return the mReliabilityOptions + */ + public ReliabilityOptions getReliabilityOptions() { + return mReliabilityOptions; + } + + /** + * @param mReliabilityOptions the mReliabilityOptions to set + */ + public void setReliabilityOptions(ReliabilityOptions mReliabilityOptions) { + this.mReliabilityOptions = mReliabilityOptions; + } + /* + * class ReOpener implements Runnable { + * + * private WebSocketClientEvent mEvent; + * + * public ReOpener(WebSocketClientEvent aEvent) { mEvent = aEvent; } + * + * @Override public void run() { notifyReconnecting(mEvent); try { + * open(mURI.toString()); } catch (WebSocketException ex) { // TODO: process + * potential exception here! } } } + */ + + /** + * @return the mHeaders + */ + public Headers getHeaders() { + return mHeaders; + } + + class ReOpener implements Runnable { + + private WebSocketClientEvent mEvent; + + public ReOpener(WebSocketClientEvent aEvent) { + mEvent = aEvent; + } + + public void run() { + mIsReconnecting = false; + notifyReconnecting(mEvent); + try { + open(mURI.toString()); + // did we configure reliability options? + /* + * if (mReliabilityOptions != null && + * mReliabilityOptions.getReconnectDelay() > 0) { + * mExecutor.schedule( new ReOpener(aEvent), + * mReliabilityOptions.getReconnectDelay(), + * TimeUnit.MILLISECONDS); } + */ + } catch (Exception lEx) { + WebSocketClientEvent lEvent = + new WebSocketBaseClientEvent(mEvent.getClient(), EVENT_CLOSE, + lEx.getClass().getSimpleName() + ": " + + lEx.getMessage()); + notifyClosed(lEvent); + } + } + } + + private void mAbortReconnect() { + synchronized (mReconnectLock) { + // cancel running re-connect task + if (null != mReconnectorTask) { + mReconnectorTask.cancel(true); + } + // reset internal re-connection flag + mIsReconnecting = false; + mReconnectorTask = null; + // clean up all potentially old references to inactive tasks + mExecutor.purge(); + } + } + + private void mCheckReconnect(WebSocketClientEvent aEvent) { + synchronized (mReconnectLock) { + // first, purge all potentially old references to other tasks + mExecutor.purge(); + // did we configure reliability options? + // and is there now re-connection task already active? + if (mReliabilityOptions != null + && mReliabilityOptions.getReconnectDelay() > 0 + && !mIsReconnecting) { + // schedule a re-connect action after the re-connect delay + mIsReconnecting = true; + mReconnectorTask = mExecutor.schedule( + new ReOpener(aEvent), + mReliabilityOptions.getReconnectDelay(), + TimeUnit.MILLISECONDS); + } + } + } + + /** + * {@inheritDoc} + */ + public void notifyClosed(WebSocketClientEvent aEvent) { + for (WebSocketClientListener lListener : getListeners()) { + lListener.processClosed(aEvent); + } + } + + public void addSubProtocol(WebSocketSubProtocol aSubProt) { + if (mSubprotocols == null) { + mSubprotocols = new ArrayList(3); + } + mSubprotocols.add(aSubProt); + } + + public String getNegotiatedSubProtocol() { + return mNegotiatedSubProtocol == null ? null : mNegotiatedSubProtocol.getSubProt(); + } + + public WebSocketEncoding getNegotiatedEncoding() { + return mNegotiatedSubProtocol == null ? null : mNegotiatedSubProtocol.getEncoding(); + } + + public void setVersion(int aVersion) { + this.mVersion = aVersion; + } + + private boolean isHixie() { + return WebSocketProtocolAbstraction.isHixieVersion(mVersion); + } + + class WebSocketReceiver extends Thread { + + private WebSocketClient mClient = null; + private InputStream mIS = null; + private volatile boolean mIsRunning = false; + + public WebSocketReceiver(WebSocketClient aClient, InputStream aInput) { + mClient = aClient; + mIS = aInput; + } + + @Override + public void run() { + Thread.currentThread().setName("jWebSocket-Client " + getId()); + + mIsRunning = true; + + // the hixie and hybi processors handle potential exceptions + if (isHixie()) { + processHixie(); + } else { + processHybi(); + } + + // set status AFTER close frame was sent, otherwise sending + // close frame leads to an exception. + mStatus = WebSocketStatus.CLOSING; + String lExMsg = ""; + try { + // shutdown methods are not implemented for SSL sockets + if (!(mSocket instanceof SSLSocket)) { + if (!mSocket.isOutputShutdown()) { + mSocket.shutdownInput(); + } + } + } catch (IOException lIOEx) { + lExMsg += "Shutdown input: " + lIOEx.getMessage() + ", "; + } + try { + // shutdown methods are not implemented for SSL sockets + if (!(mSocket instanceof SSLSocket)) { + if (!mSocket.isOutputShutdown()) { + mSocket.shutdownOutput(); + } + } + } catch (IOException lIOEx) { + lExMsg += "Shutdown output: " + lIOEx.getMessage() + ", "; + } + try { + if (!mSocket.isClosed()) { + mSocket.close(); + } + } catch (IOException lIOEx) { + lExMsg += "Socket close: " + lIOEx.getMessage() + ", "; + } + + // now the connection is really closed + // set the status accordingly + mStatus = WebSocketStatus.CLOSED; + + WebSocketClientEvent lEvent = + new WebSocketBaseClientEvent(mClient, EVENT_CLOSE, mCloseReason); + // notify listeners that client has closed + notifyClosed(lEvent); + + quit(); + + if (!CR_CLIENT.equals(mCloseReason)) { + mCheckReconnect(lEvent); + } + } + + private void processHixie() { + boolean lFrameStart = false; + ByteArrayOutputStream lBuff = new ByteArrayOutputStream(); + while (mIsRunning) { + try { + int lB = mIS.read(); + // TODO: support binary frames + if (lB == 0x00) { + lFrameStart = true; + } else if (lB == 0xff && lFrameStart == true) { + lFrameStart = false; + + WebSocketClientEvent lWSCE = new WebSocketTokenClientEvent(mClient, null, null); + RawPacket lPacket = new RawPacket(lBuff.toByteArray()); + + lBuff.reset(); + notifyPacket(lWSCE, lPacket); + } else if (lFrameStart == true) { + lBuff.write(lB); + } else if (lB == -1) { + setCloseReason("Inbound stream terminated"); + mIsRunning = false; + } + } catch (Exception lEx) { + mIsRunning = false; + setCloseReason(lEx.getClass().getName() + " in hybi processor: " + lEx.getMessage()); + } + } + } + + private void processHybi() { + WebSocketClientEvent lWSCE; + WebSocketFrameType lFrameType; + + while (mIsRunning) { + try { + WebSocketPacket lPacket = WebSocketProtocolAbstraction.protocolToRawPacket(mVersion, mIS); + lFrameType = (lPacket != null ? lPacket.getFrameType() : WebSocketFrameType.INVALID); + if (null == lFrameType) { + if (mIsRunning) { + setCloseReason("Connection broken"); + } else { + setCloseReason("Client terminated"); + } + mIsRunning = false; + } else if (WebSocketFrameType.INVALID == lFrameType) { + mIsRunning = false; + setCloseReason("Invalid hybi frame type detected"); + } else if (WebSocketFrameType.CLOSE == lFrameType) { + mIsRunning = false; + setCloseReason("Server closed connection"); + } else if (WebSocketFrameType.PING == lFrameType) { + WebSocketPacket lPong = new RawPacket( + WebSocketFrameType.PONG, ""); + send(lPong); + } else if (WebSocketFrameType.PONG == lFrameType) { + // TODO: need to process connection management here! + } else if (WebSocketFrameType.TEXT == lFrameType) { + lWSCE = new WebSocketTokenClientEvent(mClient, null, null); + notifyPacket(lWSCE, lPacket); + } else if (WebSocketFrameType.BINARY == lFrameType) { + lWSCE = new WebSocketTokenClientEvent(mClient, null, null); + notifyPacket(lWSCE, lPacket); + } + } catch (Exception lEx) { + mIsRunning = false; + setCloseReason(lEx.getClass().getName() + " in hybi processor: " + lEx.getMessage()); + } + } + } + + public void quit() { + // ensure that reader loops are not continued + mIsRunning = false; + try { + mIS.close(); + } catch (IOException ex) { + // just to force client reader to stop + } + } + + public boolean isRunning() { + return mIsRunning; + } + } +} diff --git a/simplPlatformSpecifics/Android/src/ecologylab/oodss/distributed/client/WebSocketOODSSClient.java b/simplAndroidSpecifics/src/ecologylab/oodss/distributed/client/WebSocketOODSSClient.java similarity index 100% rename from simplPlatformSpecifics/Android/src/ecologylab/oodss/distributed/client/WebSocketOODSSClient.java rename to simplAndroidSpecifics/src/ecologylab/oodss/distributed/client/WebSocketOODSSClient.java diff --git a/simplPlatformSpecifics/Android/src/ecologylab/oodss/distributed/client/WebSocketOODSSConnectionCallbacks.java b/simplAndroidSpecifics/src/ecologylab/oodss/distributed/client/WebSocketOODSSConnectionCallbacks.java similarity index 95% rename from simplPlatformSpecifics/Android/src/ecologylab/oodss/distributed/client/WebSocketOODSSConnectionCallbacks.java rename to simplAndroidSpecifics/src/ecologylab/oodss/distributed/client/WebSocketOODSSConnectionCallbacks.java index 80f843c4..ff1d1a8a 100644 --- a/simplPlatformSpecifics/Android/src/ecologylab/oodss/distributed/client/WebSocketOODSSConnectionCallbacks.java +++ b/simplAndroidSpecifics/src/ecologylab/oodss/distributed/client/WebSocketOODSSConnectionCallbacks.java @@ -1,6 +1,6 @@ -package ecologylab.oodss.distributed.client; - -public interface WebSocketOODSSConnectionCallbacks -{ - public void webSocketConnected(); -} +package ecologylab.oodss.distributed.client; + +public interface WebSocketOODSSConnectionCallbacks +{ + public void webSocketConnected(); +} diff --git a/simplPlatformSpecifics/Android/src/ecologylab/oodss/distributed/impl/MessageWithUid.java b/simplAndroidSpecifics/src/ecologylab/oodss/distributed/impl/MessageWithUid.java similarity index 94% rename from simplPlatformSpecifics/Android/src/ecologylab/oodss/distributed/impl/MessageWithUid.java rename to simplAndroidSpecifics/src/ecologylab/oodss/distributed/impl/MessageWithUid.java index 0183bc4d..4e091704 100644 --- a/simplPlatformSpecifics/Android/src/ecologylab/oodss/distributed/impl/MessageWithUid.java +++ b/simplAndroidSpecifics/src/ecologylab/oodss/distributed/impl/MessageWithUid.java @@ -1,24 +1,24 @@ -package ecologylab.oodss.distributed.impl; - -import ecologylab.oodss.messages.ServiceMessage; - -public class MessageWithUid { - private ServiceMessage message; - private long uid; - - public MessageWithUid(ServiceMessage message, long uid) - { - this.message = message; - this.uid = uid; - } - - public ServiceMessage getMessage() - { - return message; - } - - public long getUid() - { - return uid; - } -} +package ecologylab.oodss.distributed.impl; + +import ecologylab.oodss.messages.ServiceMessage; + +public class MessageWithUid { + private ServiceMessage message; + private long uid; + + public MessageWithUid(ServiceMessage message, long uid) + { + this.message = message; + this.uid = uid; + } + + public ServiceMessage getMessage() + { + return message; + } + + public long getUid() + { + return uid; + } +} diff --git a/simplPlatformSpecifics/Android/src/ecologylab/platformspecifics/FundamentalPlatformSpecificsAndroid.java b/simplAndroidSpecifics/src/ecologylab/platformspecifics/FundamentalPlatformSpecificsAndroid.java similarity index 100% rename from simplPlatformSpecifics/Android/src/ecologylab/platformspecifics/FundamentalPlatformSpecificsAndroid.java rename to simplAndroidSpecifics/src/ecologylab/platformspecifics/FundamentalPlatformSpecificsAndroid.java diff --git a/simplPlatformSpecifics/Android/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLParserAndroid.java b/simplAndroidSpecifics/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLParserAndroid.java similarity index 100% rename from simplPlatformSpecifics/Android/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLParserAndroid.java rename to simplAndroidSpecifics/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLParserAndroid.java diff --git a/simplPlatformSpecifics/Android/src/ecologylab/serialization/types/PlatformSpecificTypesAndroid.java b/simplAndroidSpecifics/src/ecologylab/serialization/types/PlatformSpecificTypesAndroid.java similarity index 96% rename from simplPlatformSpecifics/Android/src/ecologylab/serialization/types/PlatformSpecificTypesAndroid.java rename to simplAndroidSpecifics/src/ecologylab/serialization/types/PlatformSpecificTypesAndroid.java index 5d3c7feb..b43ab747 100644 --- a/simplPlatformSpecifics/Android/src/ecologylab/serialization/types/PlatformSpecificTypesAndroid.java +++ b/simplAndroidSpecifics/src/ecologylab/serialization/types/PlatformSpecificTypesAndroid.java @@ -1,16 +1,16 @@ -package ecologylab.serialization.types; - - -import ecologylab.generic.Debug; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.scalar.BitmapImageType; - -/** - * This class initializes ScalarTypes that depend on android.graphics.*, which does not exist in regular Java. - * - * @author bill - */ -public class PlatformSpecificTypesAndroid extends Debug -{ - public static final ScalarType IMAGE_TYPE = new BitmapImageType(); -} +package ecologylab.serialization.types; + + +import ecologylab.generic.Debug; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.scalar.BitmapImageType; + +/** + * This class initializes ScalarTypes that depend on android.graphics.*, which does not exist in regular Java. + * + * @author bill + */ +public class PlatformSpecificTypesAndroid extends Debug +{ + public static final ScalarType IMAGE_TYPE = new BitmapImageType(); +} diff --git a/simplPlatformSpecifics/Android/src/ecologylab/serialization/types/scalar/BitmapImageType.java b/simplAndroidSpecifics/src/ecologylab/serialization/types/scalar/BitmapImageType.java similarity index 96% rename from simplPlatformSpecifics/Android/src/ecologylab/serialization/types/scalar/BitmapImageType.java rename to simplAndroidSpecifics/src/ecologylab/serialization/types/scalar/BitmapImageType.java index 8ac9a655..8e85d8ae 100644 --- a/simplPlatformSpecifics/Android/src/ecologylab/serialization/types/scalar/BitmapImageType.java +++ b/simplAndroidSpecifics/src/ecologylab/serialization/types/scalar/BitmapImageType.java @@ -1,34 +1,34 @@ -package ecologylab.serialization.types.scalar; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; - -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; - -public class BitmapImageType extends ImageType{ - - public BitmapImageType(){ - super(Bitmap.class); - } - - @Override - public Bitmap getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - - byte[] data = stringToByteArray(value); - return BitmapFactory.decodeStream(new ByteArrayInputStream(data)); - } - - @Override - public String marshall(Bitmap value, TranslationContext suc) - { - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - value.compress(Bitmap.CompressFormat.PNG, 100, baos); - return byteArrayToString(baos.toByteArray()); - } -} +package ecologylab.serialization.types.scalar; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +public class BitmapImageType extends ImageType{ + + public BitmapImageType(){ + super(Bitmap.class); + } + + @Override + public Bitmap getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + + byte[] data = stringToByteArray(value); + return BitmapFactory.decodeStream(new ByteArrayInputStream(data)); + } + + @Override + public String marshall(Bitmap value, TranslationContext suc) + { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + value.compress(Bitmap.CompressFormat.PNG, 100, baos); + return byteArrayToString(baos.toByteArray()); + } +} diff --git a/simplCore/.classpath b/simplCore/.classpath index 8af7e3c0..3f6a80c5 100644 --- a/simplCore/.classpath +++ b/simplCore/.classpath @@ -1,11 +1,12 @@ - - - - - - - - - - - + + + + + + + + + + + + diff --git a/simplCore/.cvsignore b/simplCore/.cvsignore index b7a354bf..f2bdecd8 100644 --- a/simplCore/.cvsignore +++ b/simplCore/.cvsignore @@ -1,7 +1,7 @@ -*.esperf -*.jar -.project -.classpath -.cvsignore -doc -RESIN-CLASSES +*.esperf +*.jar +.project +.classpath +.cvsignore +doc +RESIN-CLASSES diff --git a/simplCore/.gitignore b/simplCore/.gitignore deleted file mode 100644 index 2226e8f9..00000000 --- a/simplCore/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -# java specific -*.class - -# netbeans ignore personal stuff -nbproject/private/ - - -## generic files to ignore -*~ -*.lock -*.DS_Store -*.swp -*.out - -.settings/ -bin/ - diff --git a/simplCore/.project b/simplCore/.project index 4c1da037..26476059 100644 --- a/simplCore/.project +++ b/simplCore/.project @@ -1,36 +1,47 @@ - - - simplCore - - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - net.sf.eclipsecs.core.CheckstyleBuilder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.wst.common.project.facet.core.nature - net.sf.eclipsecs.core.CheckstyleNature - - + + + simplCore + + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + net.sf.eclipsecs.core.CheckstyleBuilder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.wst.common.project.facet.core.nature + net.sf.eclipsecs.core.CheckstyleNature + + + + 1381865439638 + + 26 + + org.eclipse.ui.ide.multiFilter + 1.0-projectRelativePath-matches-false-false-build/classes + + + + diff --git a/simplCore/LICENSE.txt b/simplCore/LICENSE.txt index dc8d397c..5950277f 100644 --- a/simplCore/LICENSE.txt +++ b/simplCore/LICENSE.txt @@ -1,149 +1,149 @@ -Copyright (c) 1996-2012, Andruid Kerne and The Interface Ecology Lab - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License version 3, - as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - +Copyright (c) 1996-2012, Andruid Kerne and The Interface Ecology Lab + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + diff --git a/simplCore/Makefile b/simplCore/Makefile index 4c35f3a0..9c0f9d51 100644 --- a/simplCore/Makefile +++ b/simplCore/Makefile @@ -1,20 +1,20 @@ -# current working directory - -XML_DIR = xml xml/types/scalar xml/types/element xml/library/yahoo xml/library/dc xml/library/feedburner xml/library/media xml/library/itunes xml/library/rss xml/library/icdl xml/library/opml xml/library/geom xml/library/jnlp xml/library/jnlp/applet xml/library/jnlp/application xml/library/jnlp/information xml/library/jnlp/resource - -SERVICES = services/authentication services/authentication/listener services/authentication/logging services/authentication/messages services/authentication/nio services/authentication/registryobjects services/distributed/client services/distributed/common services/distributed/impl services/distributed/legacy services/distributed/server services/distributed/server/clientsessionmanager services/distributed/server/varieties services/exceptions services/logging services/logging/playback services/messages services/messages/cf services/distributed/exception - -FUNDAMENTAL_DIRS = appframework appframework/types appframework/types/prefs appframework/types/prefs/gui collections generic generic/text io net $(XML_DIR) $(SERVICES) - -JAR_DIRS = $(FUNDAMENTAL_DIRS:%=ecologylab/%) - -MAKE_DIR = ../../makefiles -include $(MAKE_DIR)/java.make - -TARGET = ecologylabFundamental - -jar: - rm -f $(JAR_FILE) - $(JAR) cvf $(JAR_FILE) $(JAR_CONTENTS) - cd ../ecologylabMacOS; $(JAR) uvf $(JAR_FILE) ecologylab/appframework/macos/MacOSApp.class - +# current working directory + +XML_DIR = xml xml/types/scalar xml/types/element xml/library/yahoo xml/library/dc xml/library/feedburner xml/library/media xml/library/itunes xml/library/rss xml/library/icdl xml/library/opml xml/library/geom xml/library/jnlp xml/library/jnlp/applet xml/library/jnlp/application xml/library/jnlp/information xml/library/jnlp/resource + +SERVICES = services/authentication services/authentication/listener services/authentication/logging services/authentication/messages services/authentication/nio services/authentication/registryobjects services/distributed/client services/distributed/common services/distributed/impl services/distributed/legacy services/distributed/server services/distributed/server/clientsessionmanager services/distributed/server/varieties services/exceptions services/logging services/logging/playback services/messages services/messages/cf services/distributed/exception + +FUNDAMENTAL_DIRS = appframework appframework/types appframework/types/prefs appframework/types/prefs/gui collections generic generic/text io net $(XML_DIR) $(SERVICES) + +JAR_DIRS = $(FUNDAMENTAL_DIRS:%=ecologylab/%) + +MAKE_DIR = ../../makefiles +include $(MAKE_DIR)/java.make + +TARGET = ecologylabFundamental + +jar: + rm -f $(JAR_FILE) + $(JAR) cvf $(JAR_FILE) $(JAR_CONTENTS) + cd ../ecologylabMacOS; $(JAR) uvf $(JAR_FILE) ecologylab/appframework/macos/MacOSApp.class + diff --git a/simplCore/NIOLoggingServer.launch b/simplCore/NIOLoggingServer.launch index 0ff3e103..a7af249d 100644 --- a/simplCore/NIOLoggingServer.launch +++ b/simplCore/NIOLoggingServer.launch @@ -1,14 +1,14 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/simplCore/README b/simplCore/README index e514bf51..0933ca84 100644 --- a/simplCore/README +++ b/simplCore/README @@ -1,5 +1,5 @@ -The Interface Ecology Lab ( ecologylab.net ) has recently moved all code from svn to github. - -If this repository does not have a wiki, please look at the s.im.pl guide ( http://ecologylab.net/research/simplGuide/index.html ). - -Subscribe to meta-metadata developers group ( http://groups.google.com/group/metametadata/subscribe ), or s.im.pl api developers group ( http://groups.google.com/group/ecologylabAPI/subscribe ) to see our history and ask questions. +The Interface Ecology Lab ( ecologylab.net ) has recently moved all code from svn to github. + +If this repository does not have a wiki, please look at the s.im.pl guide ( http://ecologylab.net/research/simplGuide/index.html ). + +Subscribe to meta-metadata developers group ( http://groups.google.com/group/metametadata/subscribe ), or s.im.pl api developers group ( http://groups.google.com/group/ecologylabAPI/subscribe ) to see our history and ask questions. diff --git a/simplCore/build.xml b/simplCore/build.xml index da1d847c..569ec2bb 100644 --- a/simplCore/build.xml +++ b/simplCore/build.xml @@ -1,155 +1,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + diff --git a/simplCore/config/preferences/logplaybackparams.xml b/simplCore/config/preferences/logplaybackparams.xml index 75fdf6a6..1c0a5e49 100644 --- a/simplCore/config/preferences/logplaybackparams.xml +++ b/simplCore/config/preferences/logplaybackparams.xml @@ -1,2 +1,2 @@ - + \ No newline at end of file diff --git a/simplCore/config/preferences/metaprefs.xml b/simplCore/config/preferences/metaprefs.xml index e47917fa..f5a9bfe9 100644 --- a/simplCore/config/preferences/metaprefs.xml +++ b/simplCore/config/preferences/metaprefs.xml @@ -1,33 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/simplCore/config/preferences/prefs.xml b/simplCore/config/preferences/prefs.xml index da8b94a6..5f49d568 100644 --- a/simplCore/config/preferences/prefs.xml +++ b/simplCore/config/preferences/prefs.xml @@ -1,16 +1,16 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/simplCore/config/preferences/uvaSiteGuideExample_two_clusters_v2.xml b/simplCore/config/preferences/uvaSiteGuideExample_two_clusters_v2.xml index 0e343ffd..d43a0ace 100644 --- a/simplCore/config/preferences/uvaSiteGuideExample_two_clusters_v2.xml +++ b/simplCore/config/preferences/uvaSiteGuideExample_two_clusters_v2.xml @@ -1,104 +1,104 @@ - - - - - - - - - - - - - - - - - - - - - - - Specialities - traditional - juice - Pizza - Al - Plates - tomatoes - jams - boiled - Butter - toast - Honey - tea - scrambled - sausage - Potatoes - - - - - Bar / Restaurant - restaurant - - - - - - - - - bar-rest - - - - - - - - - - - - - - - - - - - - room - double - TV - hairdryer - colour - making - en-suite - available - tea - looking - comfort - coffee - welcome - - - - Guildford Hotel - Sleep - - - - - - - accommodation - guildford-accommodation - - - - - - + + + + + + + + + + + + + + + + + + + + + + + Specialities + traditional + juice + Pizza + Al + Plates + tomatoes + jams + boiled + Butter + toast + Honey + tea + scrambled + sausage + Potatoes + + + + + Bar / Restaurant + restaurant + + + + + + + + + bar-rest + + + + + + + + + + + + + + + + + + + + room + double + TV + hairdryer + colour + making + en-suite + available + tea + looking + comfort + coffee + welcome + + + + Guildford Hotel + Sleep + + + + + + + accommodation + guildford-accommodation + + + + + + diff --git a/simplCore/eclipse/ecologylabDictionary b/simplCore/eclipse/ecologylabDictionary index e2e08eb3..0258744b 100644 --- a/simplCore/eclipse/ecologylabDictionary +++ b/simplCore/eclipse/ecologylabDictionary @@ -1,11 +1,11 @@ -zachary -toups -@ecologylab.net -zach -andruid -subdirectory -codebase -applets -avatar -websites -flipped +zachary +toups +@ecologylab.net +zach +andruid +subdirectory +codebase +applets +avatar +websites +flipped diff --git a/simplCore/eclipse/ecologylabTabsFormat.xml b/simplCore/eclipse/ecologylabTabsFormat.xml index ded45f2f..db83d31a 100644 --- a/simplCore/eclipse/ecologylabTabsFormat.xml +++ b/simplCore/eclipse/ecologylabTabsFormat.xml @@ -1,267 +1,267 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/simplCore/javadoc.xml b/simplCore/javadoc.xml deleted file mode 100644 index 5bb2e4c5..00000000 --- a/simplCore/javadoc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/simplCore/lib/ecj.jar b/simplCore/lib/ecj.jar deleted file mode 100644 index 3dbefa45..00000000 Binary files a/simplCore/lib/ecj.jar and /dev/null differ diff --git a/simplCore/lib/org.ant4eclipse_1931.jar b/simplCore/lib/org.ant4eclipse_1931.jar deleted file mode 100644 index 783621e8..00000000 Binary files a/simplCore/lib/org.ant4eclipse_1931.jar and /dev/null differ diff --git a/simplCore/lib/org.eclipse.osgi_3.2.0.v20060601.jar b/simplCore/lib/org.eclipse.osgi_3.2.0.v20060601.jar deleted file mode 100644 index 5f86e420..00000000 Binary files a/simplCore/lib/org.eclipse.osgi_3.2.0.v20060601.jar and /dev/null differ diff --git a/simplCore/lib/svnClientAdapter.jar b/simplCore/lib/svnClientAdapter.jar deleted file mode 100644 index ed37ba46..00000000 Binary files a/simplCore/lib/svnClientAdapter.jar and /dev/null differ diff --git a/simplCore/lib/svnant.jar b/simplCore/lib/svnant.jar deleted file mode 100644 index af52be0d..00000000 Binary files a/simplCore/lib/svnant.jar and /dev/null differ diff --git a/simplCore/lib/svnjavahl.jar b/simplCore/lib/svnjavahl.jar deleted file mode 100644 index 71873057..00000000 Binary files a/simplCore/lib/svnjavahl.jar and /dev/null differ diff --git a/simplCore/lib/svnkit.jar b/simplCore/lib/svnkit.jar deleted file mode 100644 index 8fe3f414..00000000 Binary files a/simplCore/lib/svnkit.jar and /dev/null differ diff --git a/simplCore/src/META-INF/MANIFEST.MF b/simplCore/src/META-INF/MANIFEST.MF new file mode 100644 index 00000000..5e949512 --- /dev/null +++ b/simplCore/src/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/simplCore/src/ecologylab/appframework/ApplicationEnvironment.java b/simplCore/src/ecologylab/appframework/ApplicationEnvironment.java index b0f68e15..cae3536e 100644 --- a/simplCore/src/ecologylab/appframework/ApplicationEnvironment.java +++ b/simplCore/src/ecologylab/appframework/ApplicationEnvironment.java @@ -1,1097 +1,1097 @@ -package ecologylab.appframework; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLDecoder; -import java.util.Stack; - -import ecologylab.appframework.types.prefs.Pref; -import ecologylab.appframework.types.prefs.PrefEnum; -import ecologylab.appframework.types.prefs.PrefSet; -import ecologylab.appframework.types.prefs.PrefSetBaseClassProvider; -import ecologylab.collections.Scope; -import ecologylab.generic.Debug; -import ecologylab.io.DownloadProcessor; -import ecologylab.io.Files; -import ecologylab.io.ZipDownload; -import ecologylab.net.ParsedURL; -import ecologylab.platformspecifics.FundamentalPlatformSpecifics; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.XMLTranslationExceptionTypes; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * An instance of Environment, which is an application, rather than an applet, or a servlet. The - * Environment mechanism is used to enable the provision of contextual runtime configuration - * parameter services in a way that is independent of the deployment structure. - * - * @author Andruid - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class ApplicationEnvironment extends Debug implements Environment, - XMLTranslationExceptionTypes, ApplicationPropertyNames -{ - - static - { - FundamentalPlatformSpecifics.get().initializePlatformSpecificTranslation(); - } - - public static final PrefEnum LAUNCH_TYPE_PREF = Pref.usePrefEnum( LAUNCH_TYPE, - LaunchType.ECLIPSE); - - /** Subdirectory for eclipse launches. */ - protected static final String ECLIPSE_PREFS_DIR = "config/preferences/"; - - public static final String PREFERENCES = "preferences/"; - - protected The the = new The(); - - Scope sessionScope; - - SimplTypesScope translationScope; - - /** - * Used for forming codeBase relative ParsedURLs. A simulation of the property available in - * applets. The codebase is the address where the java code comes from. - */ - ParsedURL codeBase; - - /** - * Used for forming codeBase relative ParsedURLs. A simulation of the property available in - * applets. The docbase is the address where the launching HTML file comes from. - */ - ParsedURL docBase; - - /** Set of actual Prefs being used locally. */ - PrefSet prefSet; - - /** Place where Prefs are loaded from and stored to. */ - protected ParsedURL prefsPURL; - - protected String applicationName; - - protected enum LaunchType - { - JNLP, LOCAL_JNLP, ECLIPSE, JAR, STUDIES, - } - - protected LaunchType launchType; - - /** Stores the argument stack for use by subclasses. */ - protected Stack argStack; - - /** - * Create an ApplicationEnvironment. Create an empty properties object for application parameters. - *

- * No command line argument is processed. Only default preferences are loaded, and processed with - * the default TranslationSpace. - * - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @throws SIMPLTranslationException - */ - public ApplicationEnvironment(String applicationName) throws SIMPLTranslationException - { - this(null, applicationName, null); - } - - /** - * Create an ApplicationEnvironment. Load preferences from XML file founds in the - * config/preferences directory. Default preferences will be loaded from preferences.xml. If there - * is a 0th command line argument, that is the name of an additional preferences file. - * - * @param applicationName - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - public ApplicationEnvironment(String applicationName, - SimplTypesScope translationScope, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this(applicationName, translationScope, (SimplTypesScope) null, args, prefsAssetVersion); - } - - /** - * Create an ApplicationEnvironment. Load preferences from XML file founds in the - * config/preferences directory. Default preferences will be loaded from preferences.xml. If there - * is a 0th command line argument, that is the name of an additional preferences file. - * - * @param applicationName - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param customPrefs - * TODO - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - public ApplicationEnvironment(String applicationName, - SimplTypesScope translationScope, - Class>[] customPrefs, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this(applicationName, (Scope) null, translationScope, customPrefs, args, prefsAssetVersion); - } - - /** - * - * @param applicationName - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param sessionScope - * @param customPrefs - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * @throws SIMPLTranslationException - */ - public ApplicationEnvironment(String applicationName, - Scope sessionScope, - SimplTypesScope translationScope, - Class>[] customPrefs, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this( (Class) null, - applicationName, - sessionScope, - translationScope, - prefsClassArrayToTranslationScope(customPrefs), - args, - prefsAssetVersion); - } - - /** - * Create an ApplicationEnvironment. Load preferences from XML file founds in the - * config/preferences directory. Default preferences will be loaded from preferences.xml. If there - * is a 0th command line argument, that is the name of an additional preferences file. - * - * @param applicationName - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param customPrefsTranslationScope - * TODO - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - public ApplicationEnvironment(String applicationName, - SimplTypesScope translationScope, - SimplTypesScope customPrefsTranslationScope, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this( (Class) null, - applicationName, - (Scope) null, - translationScope, - customPrefsTranslationScope, - args, - prefsAssetVersion); - } - - /** - * Configures a TranslationScope for the PREFS_TRANSLATION_SCOPE using the given customPrefs and - * returns it. - * - * @param customPrefs - * @return - */ - protected static final SimplTypesScope prefsClassArrayToTranslationScope( - Class>[] customPrefs) - { - // configure the PrefSet translation scope, incorporating custom translations, if any - if (customPrefs == null) - customPrefs = PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses(); - - return SimplTypesScope.get(PrefSet.PREFS_TRANSLATION_SCOPE, customPrefs); - } - - /** - * Create an ApplicationEnvironment. Load preferences from XML files found in the - * config/preferences directory. Default preferences will be loaded from preferences.xml. If there - * is a 0th command line argument, that is the name of an additional preferences file. - *

- * The default TranslationSpace, from - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * - * @param applicationName - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @throws SIMPLTranslationException - */ - public ApplicationEnvironment(String applicationName, String args[]) - throws SIMPLTranslationException - { - this(applicationName, (SimplTypesScope) null, (SimplTypesScope) null, args, 0); - } - - /** - * Create an ApplicationEnvironment. Get the base for finding the path to the "codeBase" by using - * the package path of the baseClass passed in. - *

- * Load preferences from XML file founds in the codeBase/config/preferences directory. Default - * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that - * is the name of an additional preferences file. - *

- * Also, sets the Assets cacheRoot to the applicationDir(). - *

- * The default TranslationSpace, from - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * - * @param baseClass - * Used for computing codeBase property. - * @param applicationName - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full - * @throws SIMPLTranslationException - */ - public ApplicationEnvironment(Class baseClass, String applicationName, String args[]) - throws SIMPLTranslationException - { - this(baseClass, applicationName, null, null, null, args, 0); - } - - /** - * Additional constructor to hold the session scope for post processing loaded preferences. - * - * @param applicationName - * @param sessionScope - */ - public ApplicationEnvironment(Class baseClass, - String applicationName, - SimplTypesScope translationScope, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this(baseClass, applicationName, null, translationScope, null, args, prefsAssetVersion); - } - - /** - * Create an ApplicationEnvironment. - *

- * Treats the args array like a stack. If any args are missing (based on their format), they are - * skipped. - *

- * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local - * relative path, or a URL-based absolute path. - *

- * The next possible arg is a preferences file. This ends with .xml. - *

- * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen - * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost - * half; 3; near full; 4 full - *

- * Get the base for finding the path to the "codeBase" by using the package path of the baseClass - * passed in. - *

- * Load preferences from XML file founds in the codeBase/config/preferences directory. Default - * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that - * is the name of an additional preferences file. - *

- * Also, sets the Assets cacheRoot to the applicationDir(). - *

- * The default TranslationSpace, from - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * - * @param baseClass - * Used for computing codeBase property. - * @param applicationName - * Name of the application. - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - public ApplicationEnvironment(Class baseClass, - String applicationName, - Scope sessionScope, - SimplTypesScope translationScope, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this(baseClass, applicationName, sessionScope, translationScope, null, args, prefsAssetVersion); - } - - /** - * Create an ApplicationEnvironment. - *

- * Treats the args array like a stack. If any args are missing (based on their format), they are - * skipped. - *

- * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local - * relative path, or a URL-based absolute path. - *

- * The next possible arg is a preferences file. This ends with .xml. - *

- * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen - * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost - * half; 3; near full; 4 full - *

- * Get the base for finding the path to the "codeBase" by using the package path of the baseClass - * passed in. - *

- * Load preferences from XML file founds in the codeBase/config/preferences directory. Default - * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that - * is the name of an additional preferences file. - *

- * Also, sets the Assets cacheRoot to the applicationDir(). - *

- * The default TranslationSpace, from - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * - * @param baseClass - * Used for computing codeBase property. - * @param applicationName - * Name of the application. - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param customPrefs - * An array of Pref subclasses that are used for this specific application. These classes - * will be automatically composed into a special translation scope used for translating - * prefs for the application. Note that translationScope is NOT used for translating the - * application prefs, but is still required for other translations in the application. - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - public ApplicationEnvironment(Class baseClass, - String applicationName, - Scope sessionScope, - SimplTypesScope translationScope, - SimplTypesScope customPrefsTranslationScope, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this( baseClass, - applicationName, - sessionScope, - translationScope, - customPrefsTranslationScope, - makeStack(args), - prefsAssetVersion); - } - - /** - * Create an ApplicationEnvironment. - *

- * Treats the args array like a stack. If any args are missing (based on their format), they are - * skipped. - *

- * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local - * relative path, or a URL-based absolute path. - *

- * The next possible arg is a preferences file. This ends with .xml. - *

- * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen - * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost - * half; 3; near full; 4 full - *

- * Get the base for finding the path to the "codeBase" by using the package path of the baseClass - * passed in. - *

- * Load preferences from XML file founds in the codeBase/config/preferences directory. Default - * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that - * is the name of an additional preferences file. - *

- * Also, sets the Assets cacheRoot to the applicationDir(). - *

- * The default TranslationSpace, from - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * - * @param baseClass - * Used for computing codeBase property. - * @param applicationName - * Name of the application. - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param customPrefs - * An array of Pref subclasses that are used for this specific application. These classes - * will be automatically composed into a special translation scope used for translating - * prefs for the application. Note that translationScope is NOT used for translating the - * application prefs, but is still required for other translations in the application. - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - public ApplicationEnvironment(Class baseClass, - String applicationName, - Scope sessionScope, - SimplTypesScope translationScope, - SimplTypesScope customPrefsTranslationScope, - Stack argStack, - float prefsAssetVersion) throws SIMPLTranslationException - { - this.argStack = argStack; - - // setup the translations used for prefs - SimplTypesScope prefTranslations; - if (customPrefsTranslationScope != null) - { - SimplTypesScope[] arrayToMakeJavaShutUp = - { customPrefsTranslationScope }; - prefTranslations = SimplTypesScope.get(PrefSet.PREFS_TRANSLATION_SCOPE, - arrayToMakeJavaShutUp, - PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses()); - } - else - { - Class[] customPrefs = PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses(); - - prefTranslations = SimplTypesScope.get(PrefSet.PREFS_TRANSLATION_SCOPE, customPrefs); - } - - this.sessionScope = sessionScope; - - setApplicationName(applicationName); - - // setup os specific system preferences - PropertiesAndDirectories.setOSSpecificProperties(this.applicationName); - - ZipDownload.setDownloadProcessor(assetsDownloadProcessor()); - - if (translationScope == null) - // default translation scope changed by andruid 5/27/10 - translationScope = prefTranslations; - // translationScope = DefaultServicesTranslations.get(); - - this.translationScope = translationScope; - - processArgsAndPrefs(baseClass, translationScope, prefsAssetVersion); - } - - /** - * Sets this.applicationName. - * - * @param applicationName - */ - protected void setApplicationName(String applicationName) - { - this.applicationName = applicationName; - } - - /** Convert the args array into a Stack. */ - protected static Stack makeStack(String[] strings) - { - Stack retStack = new Stack(); - - if (strings != null) - for (int i = strings.length - 1; i >= 0; i--) - retStack.push(strings[i]); - - return retStack; - } - - protected void processArgsAndPrefs(Class baseClass, SimplTypesScope translationScope, - float prefsAssetVersion) throws SIMPLTranslationException - { - processPrefs(baseClass, translationScope, argStack, prefsAssetVersion); - - Debug.initialize(); - } - - /** - * request User's prefSet from the preferenceServlet and return the prefSetXML string. - * - * @author eunyee - * @param prefServlet - * @param translationScope - * TODO - * @param uid - * @return - */ - protected PrefSet requestPrefFromServlet(String prefServlet, SimplTypesScope translationScope) - { - System.out.println("retrieving preferences set from servlet: " + prefServlet); - - try - { - URL url = new URL(prefServlet); - URLConnection connection = url.openConnection(); - - // specify the content type that binary data is sent - connection.setRequestProperty("Content-Type", "text/xml"); - - // define a new BufferedReader on the input stream - BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); - - // receive data from the servlet - String prefSetXML = in.readLine(); - PrefSet prfs = null; - try - { - prfs = PrefSet.loadFromCharSequence(prefSetXML, translationScope); - System.out.println("Prefs loaded From Servlet:: "); - if (prfs != null) - SimplTypesScope.serialize(prfs, System.out, StringFormat.XML); - - System.out.println(" --- End Prefs"); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - in.close(); - - return prfs; - } - catch (IOException e) - { - warning("not a servlet URL: " + prefServlet); - } - return null; - } - - /** - * Load Prefs, if possible - * - * @param baseClass - * @param translationScope - * @param argStack - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - private void processPrefs(Class baseClass, SimplTypesScope translationScope, - Stack argStack, float prefsAssetVersion) throws SIMPLTranslationException - { - LaunchType launchType = LaunchType.ECLIPSE; // current default - - // look for launch method identifier in upper case - String arg = pop(argStack); - - if (arg != null) - { - String uc = arg.toUpperCase(); - if ("JNLP".equals(uc)) - { // tells us how we were launched: e.g., JNLP, ECLIPSE, ... - launchType = LaunchType.JNLP; - } - else if ("STUDIES".equals(uc)) - { - launchType = LaunchType.STUDIES; - } - else - { - // TODO -- recognize JAR here !!! - argStack.push(arg); - } - LAUNCH_TYPE_PREF.setValue(launchType); - } - println("LaunchType = " + launchType); - this.launchType = launchType; - // look for codeBase path - arg = pop(argStack); - - // read perhaps meta-preferences and surely preferences from application data dir - File applicationDir = PropertiesAndDirectories.thisApplicationDir(this); - - ParsedURL applicationDataPURL = new ParsedURL(applicationDir); - prefsPURL = applicationDataPURL.getRelative("preferences/prefs.xml"); - debugA("prefsPURL= " + prefsPURL); - - System.out.println("arg: " + arg); - - switch (launchType) - { - case STUDIES: - case JNLP: - // next arg *should* be code base - if ((arg != null) && arg.endsWith("/")) - { - // JNLP only! (as of now) - // right now this only works for http:// - ParsedURL codeBase = ParsedURL.getAbsolute(arg, "Setting up codebase"); - this.setCodeBase(codeBase); - - // from supplied URL instead of from here - try - { - debugA("Considering prefSet=" + prefSet + "\tprefsPURL=" + prefsPURL); - if (prefSet == null) // Normal Case - { - prefSet = PrefSet.load(prefsPURL, translationScope); - if (prefSet != null) - println("OK: Loaded Prefs from " + prefsPURL); - else - println("No Prefs to load from " + prefsPURL); - } - } - catch (SIMPLTranslationException e) - { - // meta prefs o.k. we can continue - warning("Couldn't load Prefs:"); - e.printTraceOrMessage(this, "Prefs", prefsPURL); - println("\tContinuing."); - } - - debugA("argStack.size() = " + argStack.size()); - if (argStack.size() > 0) - { - String prefSpec = ""; - if (arg.startsWith("http://")) - { - // PreferencesServlet - prefSpec = pop(argStack); - - if (prefSpec != null) - { - // load URLEncoded prefs XML straight from the argument - PrefSet JNLPPrefSet = loadPrefsFromJNLP(prefSpec); - - if (JNLPPrefSet != null) - { - if (prefSet == null) - prefSet = JNLPPrefSet; - else - prefSet.append(JNLPPrefSet); - } - else - { // if we got args straight from jnlp, then continue - if (JNLPPrefSet != null) - prefSpec = pop(argStack); - - if (prefSpec != null) - { - PrefSet servletPrefSet = requestPrefFromServlet(prefSpec, translationScope); - if (servletPrefSet == null) - error("incorrect prefXML string returned from the servlet=" + prefSpec); - else - { - if (prefSet == null) - prefSet = servletPrefSet; - else - prefSet.append(servletPrefSet); - } - } - } - } - } - } - } - else - { - error("No code base argument :-( Can't load preferences."); - } - break; - case ECLIPSE: - case JAR: - // NB: This gets executed even if arg was null! - File localCodeBasePath = deriveLocalFileCodeBase(baseClass); // sets codeBase()! - argStack.push(arg); - - // load the application dir prefs from this machine - // (e.g., c:\Documents and Settings\andruid\Application - // Data\combinFormation\preferences\prefs.xml - // these are the ones that get edited interactively! - - prefSet = PrefSet.load(prefsPURL, translationScope); - if (prefSet != null) - println("Loaded Prefs from: " + prefsPURL); - else - println("No Prefs to load from: " + prefsPURL); - - // now seek the path to an application specific xml preferences file - arg = pop(argStack); - // if (arg == null) - // return; - if (arg != null) - { - // load preferences specific to this invocation - if (arg.endsWith(".xml")) - { - File argPrefsFile = new File(localCodeBasePath, ECLIPSE_PREFS_DIR + arg); - ParsedURL argPrefsPURL = new ParsedURL(argPrefsFile); - try - { - PrefSet argPrefSet = PrefSet.load(argPrefsPURL, translationScope); - - if (argPrefSet != null) - { - println("OK: Loaded Prefs from: " + argPrefsFile); - if (prefSet != null) - prefSet.addPrefSet(argPrefSet); - else - prefSet = argPrefSet; - } - else - { - println(""); - String doesntExist = argPrefsFile.exists() ? "" : "\n\tFile does not exist!!!\n\n"; - println("ERROR: Loading Prefs from: " + argPrefsFile + doesntExist); - } - - } - catch (SIMPLTranslationException e) - { - // meta prefs o.k. we can continue without having loaded Prefs now - e.printTraceOrMessage(this, "Couldn't load Prefs", argPrefsPURL); - println("\tContinuing."); - } - } - else - argStack.push(arg); - } - else - argStack.push(arg); // let the next code handle returning. - break; - } - System.out.println("Printing Prefs:\n"); - try - { - if (prefSet != null) - SimplTypesScope.serialize(prefSet, System.out, StringFormat.XML); - - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - System.out.println("\nPrefs Printed"); - if (prefSet != null) - postProcessPrefs(prefSet); - } - - /** - * Look for pref Ops, if delayed: setup their timers, and also set scope for their ops. - * - * @param prefSet - */ - private void postProcessPrefs(PrefSet prefSet) - { - if (sessionScope == null) - return; - for (Pref pref : prefSet.values()) - if (pref != null) - pref.postLoadHook(sessionScope); - } - - private PrefSet loadPrefsFromJNLP(String prefSpec) - { - PrefSet prefSet = null; - - debugA("loadPrefsFromJNLP()"); - if (prefSpec.startsWith("%3Cpref_set")) - { - try - { - String decodedPrefsXML = URLDecoder.decode(prefSpec, "UTF-8"); - debugA("Loading prefs from JNLP: " + decodedPrefsXML); - -// debugA("TranslationScope: \n"); -// for (ClassDescriptor c : translationScope.getClassDescriptors()) -// { -// debugA(c.toString()); -// } - - prefSet = PrefSet.loadFromCharSequence(decodedPrefsXML, translationScope); - } - catch (UnsupportedEncodingException e) - { - e.printStackTrace(); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - } - return prefSet; - } - - /** - * Get the user.dir property. Form a path from it, ending in slash. See if there is path within - * that that includes the package of baseClass. If so, remove that component from the path. - * - * Form a File from this path, and a ParsedURL from the file. Set codeBase to this ParsedURL. - * - * @param baseClass - * Class of the subclass of this that is the main program that was executed. - * - * @return File that corresponds to the path of the local codeBase. - */ - protected File deriveLocalFileCodeBase(Class baseClass) - { - // setup codeBase - if (baseClass == null) - baseClass = this.getClass(); - - Package basePackage = baseClass.getPackage(); - String packageName = basePackage.getName(); - String packageNameAsPath = packageName.replace('.', Files.sep); - - String pathName = System.getProperty("user.dir") + Files.sep; - File path = new File(pathName); - String pathString = path.getAbsolutePath(); - - int packageIndex = pathString.lastIndexOf(packageNameAsPath); - if (packageIndex != -1) - { - pathString = pathString.substring(0, packageIndex); - path = new File(pathString + Files.sep); - } - - codeBase = new ParsedURL(path); - println("codeBase=" + codeBase); - return path; - } - - /** - * @see ecologylab.appframework.Environment#runtimeEnv() - */ - @Override - public int runtimeEnv() - { - return APPLICATION; - } - - /** - * @see ecologylab.appframework.Environment#status(String) - */ - public void showStatus(String s) - { - System.out.println(s); - } - - /** - * @see ecologylab.appframework.Environment#status(String) - */ - @Override - public void status(String msg) - { - if (msg != null) - showStatus(msg); - } - - /** - * @see ecologylab.appframework.Environment#codeBase() return the path to root of the - */ - @Override - public ParsedURL codeBase() - { - return codeBase; - } - - /** - * @see ecologylab.appframework.Environment#docBase() return the current working directory of the - * application which is "c:\web\code\java\cm" - */ - @Override - public ParsedURL docBase() - { - ParsedURL purl = new ParsedURL(new File(System.getProperty("user.dir"))); - return purl; - } - - public ParsedURL preferencesDir() - { - ParsedURL codeBase = codeBase(); - ParsedURL purl = codeBase.getRelative(ECLIPSE_PREFS_DIR, "forming preferences dir"); - return purl; - } - - /** - * Set the codebase for the application. Should only be done at startup. - */ - public void setCodeBase(ParsedURL codeBase) - { - this.codeBase = codeBase; - } - - protected static T pop(Stack stack) - { - return stack.isEmpty() ? null : stack.pop(); - } - - /** - * Translation space used to parse Preferences for this Application. - * - * @return TranslationSpace in use for parsing Preferences - */ - public SimplTypesScope translationScope() - { - return translationScope; - } - - public DownloadProcessor assetsDownloadProcessor() - { - return new SimpleDownloadProcessor(); - } - - /** - * Remove the Pref from the PrefSet associated with this, and from the global set. - * - * @param key - * @return - */ - public void clearPref(String key) - { - if (prefSet != null) - prefSet.clearPref(key); - } - - /** - * - * @return The set of Prefs associated with this application. - */ - protected PrefSet prefSet() - { - return prefSet; - } - - /** - * Adds otherPrefs to this.prefSet, replacing any entries with the same name. - * - * @param otherPrefs - */ - protected void augmentPrefSet(PrefSet otherPrefs) - { - if (prefSet == null) - { - synchronized (this) - { - if (prefSet == null) - this.prefSet = new PrefSet(); - } - } - - synchronized (prefSet) - { - for (String k : otherPrefs.keySet()) - { - this.prefSet.put(k, otherPrefs.get(k)); - } - } - } - - /** - * TODO Not sure how we can handle this in a non-static way; for now, this version does nothing. - * - * @see ecologylab.appframework.Environment#exit(int) - */ - @Override - public void exit(int code) - { - - } - - /** - * XXX not implemented - * - * @see ecologylab.appframework.Environment#navigate(ecologylab.net.ParsedURL, java.lang.String) - */ - @Override - public void navigate(ParsedURL purl, String frame) - { - - } - - /** - * XXX not implemented - * - * @see ecologylab.appframework.Environment#browser() - */ - @Override - public int browser() - { - return 0; - } - - public boolean isRunningInEclipse() - { - return LaunchType.ECLIPSE == this.launchType; - } - - public boolean isRunningLocalhost() - { - return LaunchType.LOCAL_JNLP == this.launchType; - } - - @Override - public String getApplicationName() - { - return applicationName; - } - - @Override - public boolean hasFirefox() - { - // TODO Auto-generated method stub - return false; - } -} +package ecologylab.appframework; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLDecoder; +import java.util.Stack; + +import ecologylab.appframework.types.prefs.Pref; +import ecologylab.appframework.types.prefs.PrefEnum; +import ecologylab.appframework.types.prefs.PrefSet; +import ecologylab.appframework.types.prefs.PrefSetBaseClassProvider; +import ecologylab.collections.Scope; +import ecologylab.generic.Debug; +import ecologylab.io.DownloadProcessor; +import ecologylab.io.Files; +import ecologylab.io.ZipDownload; +import ecologylab.net.ParsedURL; +import ecologylab.platformspecifics.FundamentalPlatformSpecifics; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.XMLTranslationExceptionTypes; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * An instance of Environment, which is an application, rather than an applet, or a servlet. The + * Environment mechanism is used to enable the provision of contextual runtime configuration + * parameter services in a way that is independent of the deployment structure. + * + * @author Andruid + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class ApplicationEnvironment extends Debug implements Environment, + XMLTranslationExceptionTypes, ApplicationPropertyNames +{ + + static + { + FundamentalPlatformSpecifics.get().initializePlatformSpecificTranslation(); + } + + public static final PrefEnum LAUNCH_TYPE_PREF = Pref.usePrefEnum( LAUNCH_TYPE, + LaunchType.ECLIPSE); + + /** Subdirectory for eclipse launches. */ + protected static final String ECLIPSE_PREFS_DIR = "config/preferences/"; + + public static final String PREFERENCES = "preferences/"; + + protected The the = new The(); + + Scope sessionScope; + + SimplTypesScope translationScope; + + /** + * Used for forming codeBase relative ParsedURLs. A simulation of the property available in + * applets. The codebase is the address where the java code comes from. + */ + ParsedURL codeBase; + + /** + * Used for forming codeBase relative ParsedURLs. A simulation of the property available in + * applets. The docbase is the address where the launching HTML file comes from. + */ + ParsedURL docBase; + + /** Set of actual Prefs being used locally. */ + PrefSet prefSet; + + /** Place where Prefs are loaded from and stored to. */ + protected ParsedURL prefsPURL; + + protected String applicationName; + + protected enum LaunchType + { + JNLP, LOCAL_JNLP, ECLIPSE, JAR, STUDIES, + } + + protected LaunchType launchType; + + /** Stores the argument stack for use by subclasses. */ + protected Stack argStack; + + /** + * Create an ApplicationEnvironment. Create an empty properties object for application parameters. + *

+ * No command line argument is processed. Only default preferences are loaded, and processed with + * the default TranslationSpace. + * + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @throws SIMPLTranslationException + */ + public ApplicationEnvironment(String applicationName) throws SIMPLTranslationException + { + this(null, applicationName, null); + } + + /** + * Create an ApplicationEnvironment. Load preferences from XML file founds in the + * config/preferences directory. Default preferences will be loaded from preferences.xml. If there + * is a 0th command line argument, that is the name of an additional preferences file. + * + * @param applicationName + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + public ApplicationEnvironment(String applicationName, + SimplTypesScope translationScope, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this(applicationName, translationScope, (SimplTypesScope) null, args, prefsAssetVersion); + } + + /** + * Create an ApplicationEnvironment. Load preferences from XML file founds in the + * config/preferences directory. Default preferences will be loaded from preferences.xml. If there + * is a 0th command line argument, that is the name of an additional preferences file. + * + * @param applicationName + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param customPrefs + * TODO + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + public ApplicationEnvironment(String applicationName, + SimplTypesScope translationScope, + Class>[] customPrefs, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this(applicationName, (Scope) null, translationScope, customPrefs, args, prefsAssetVersion); + } + + /** + * + * @param applicationName + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param sessionScope + * @param customPrefs + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * @throws SIMPLTranslationException + */ + public ApplicationEnvironment(String applicationName, + Scope sessionScope, + SimplTypesScope translationScope, + Class>[] customPrefs, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this( (Class) null, + applicationName, + sessionScope, + translationScope, + prefsClassArrayToTranslationScope(customPrefs), + args, + prefsAssetVersion); + } + + /** + * Create an ApplicationEnvironment. Load preferences from XML file founds in the + * config/preferences directory. Default preferences will be loaded from preferences.xml. If there + * is a 0th command line argument, that is the name of an additional preferences file. + * + * @param applicationName + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param customPrefsTranslationScope + * TODO + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + public ApplicationEnvironment(String applicationName, + SimplTypesScope translationScope, + SimplTypesScope customPrefsTranslationScope, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this( (Class) null, + applicationName, + (Scope) null, + translationScope, + customPrefsTranslationScope, + args, + prefsAssetVersion); + } + + /** + * Configures a TranslationScope for the PREFS_TRANSLATION_SCOPE using the given customPrefs and + * returns it. + * + * @param customPrefs + * @return + */ + protected static final SimplTypesScope prefsClassArrayToTranslationScope( + Class>[] customPrefs) + { + // configure the PrefSet translation scope, incorporating custom translations, if any + if (customPrefs == null) + customPrefs = PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses(); + + return SimplTypesScope.get(PrefSet.PREFS_TRANSLATION_SCOPE, customPrefs); + } + + /** + * Create an ApplicationEnvironment. Load preferences from XML files found in the + * config/preferences directory. Default preferences will be loaded from preferences.xml. If there + * is a 0th command line argument, that is the name of an additional preferences file. + *

+ * The default TranslationSpace, from + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * + * @param applicationName + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @throws SIMPLTranslationException + */ + public ApplicationEnvironment(String applicationName, String args[]) + throws SIMPLTranslationException + { + this(applicationName, (SimplTypesScope) null, (SimplTypesScope) null, args, 0); + } + + /** + * Create an ApplicationEnvironment. Get the base for finding the path to the "codeBase" by using + * the package path of the baseClass passed in. + *

+ * Load preferences from XML file founds in the codeBase/config/preferences directory. Default + * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that + * is the name of an additional preferences file. + *

+ * Also, sets the Assets cacheRoot to the applicationDir(). + *

+ * The default TranslationSpace, from + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * + * @param baseClass + * Used for computing codeBase property. + * @param applicationName + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full + * @throws SIMPLTranslationException + */ + public ApplicationEnvironment(Class baseClass, String applicationName, String args[]) + throws SIMPLTranslationException + { + this(baseClass, applicationName, null, null, null, args, 0); + } + + /** + * Additional constructor to hold the session scope for post processing loaded preferences. + * + * @param applicationName + * @param sessionScope + */ + public ApplicationEnvironment(Class baseClass, + String applicationName, + SimplTypesScope translationScope, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this(baseClass, applicationName, null, translationScope, null, args, prefsAssetVersion); + } + + /** + * Create an ApplicationEnvironment. + *

+ * Treats the args array like a stack. If any args are missing (based on their format), they are + * skipped. + *

+ * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local + * relative path, or a URL-based absolute path. + *

+ * The next possible arg is a preferences file. This ends with .xml. + *

+ * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen + * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost + * half; 3; near full; 4 full + *

+ * Get the base for finding the path to the "codeBase" by using the package path of the baseClass + * passed in. + *

+ * Load preferences from XML file founds in the codeBase/config/preferences directory. Default + * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that + * is the name of an additional preferences file. + *

+ * Also, sets the Assets cacheRoot to the applicationDir(). + *

+ * The default TranslationSpace, from + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * + * @param baseClass + * Used for computing codeBase property. + * @param applicationName + * Name of the application. + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + public ApplicationEnvironment(Class baseClass, + String applicationName, + Scope sessionScope, + SimplTypesScope translationScope, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this(baseClass, applicationName, sessionScope, translationScope, null, args, prefsAssetVersion); + } + + /** + * Create an ApplicationEnvironment. + *

+ * Treats the args array like a stack. If any args are missing (based on their format), they are + * skipped. + *

+ * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local + * relative path, or a URL-based absolute path. + *

+ * The next possible arg is a preferences file. This ends with .xml. + *

+ * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen + * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost + * half; 3; near full; 4 full + *

+ * Get the base for finding the path to the "codeBase" by using the package path of the baseClass + * passed in. + *

+ * Load preferences from XML file founds in the codeBase/config/preferences directory. Default + * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that + * is the name of an additional preferences file. + *

+ * Also, sets the Assets cacheRoot to the applicationDir(). + *

+ * The default TranslationSpace, from + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * + * @param baseClass + * Used for computing codeBase property. + * @param applicationName + * Name of the application. + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param customPrefs + * An array of Pref subclasses that are used for this specific application. These classes + * will be automatically composed into a special translation scope used for translating + * prefs for the application. Note that translationScope is NOT used for translating the + * application prefs, but is still required for other translations in the application. + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + public ApplicationEnvironment(Class baseClass, + String applicationName, + Scope sessionScope, + SimplTypesScope translationScope, + SimplTypesScope customPrefsTranslationScope, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this( baseClass, + applicationName, + sessionScope, + translationScope, + customPrefsTranslationScope, + makeStack(args), + prefsAssetVersion); + } + + /** + * Create an ApplicationEnvironment. + *

+ * Treats the args array like a stack. If any args are missing (based on their format), they are + * skipped. + *

+ * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local + * relative path, or a URL-based absolute path. + *

+ * The next possible arg is a preferences file. This ends with .xml. + *

+ * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen + * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost + * half; 3; near full; 4 full + *

+ * Get the base for finding the path to the "codeBase" by using the package path of the baseClass + * passed in. + *

+ * Load preferences from XML file founds in the codeBase/config/preferences directory. Default + * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that + * is the name of an additional preferences file. + *

+ * Also, sets the Assets cacheRoot to the applicationDir(). + *

+ * The default TranslationSpace, from + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * + * @param baseClass + * Used for computing codeBase property. + * @param applicationName + * Name of the application. + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param customPrefs + * An array of Pref subclasses that are used for this specific application. These classes + * will be automatically composed into a special translation scope used for translating + * prefs for the application. Note that translationScope is NOT used for translating the + * application prefs, but is still required for other translations in the application. + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + public ApplicationEnvironment(Class baseClass, + String applicationName, + Scope sessionScope, + SimplTypesScope translationScope, + SimplTypesScope customPrefsTranslationScope, + Stack argStack, + float prefsAssetVersion) throws SIMPLTranslationException + { + this.argStack = argStack; + + // setup the translations used for prefs + SimplTypesScope prefTranslations; + if (customPrefsTranslationScope != null) + { + SimplTypesScope[] arrayToMakeJavaShutUp = + { customPrefsTranslationScope }; + prefTranslations = SimplTypesScope.get(PrefSet.PREFS_TRANSLATION_SCOPE, + arrayToMakeJavaShutUp, + PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses()); + } + else + { + Class[] customPrefs = PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses(); + + prefTranslations = SimplTypesScope.get(PrefSet.PREFS_TRANSLATION_SCOPE, customPrefs); + } + + this.sessionScope = sessionScope; + + setApplicationName(applicationName); + + // setup os specific system preferences + PropertiesAndDirectories.setOSSpecificProperties(this.applicationName); + + ZipDownload.setDownloadProcessor(assetsDownloadProcessor()); + + if (translationScope == null) + // default translation scope changed by andruid 5/27/10 + translationScope = prefTranslations; + // translationScope = DefaultServicesTranslations.get(); + + this.translationScope = translationScope; + + processArgsAndPrefs(baseClass, translationScope, prefsAssetVersion); + } + + /** + * Sets this.applicationName. + * + * @param applicationName + */ + protected void setApplicationName(String applicationName) + { + this.applicationName = applicationName; + } + + /** Convert the args array into a Stack. */ + protected static Stack makeStack(String[] strings) + { + Stack retStack = new Stack(); + + if (strings != null) + for (int i = strings.length - 1; i >= 0; i--) + retStack.push(strings[i]); + + return retStack; + } + + protected void processArgsAndPrefs(Class baseClass, SimplTypesScope translationScope, + float prefsAssetVersion) throws SIMPLTranslationException + { + processPrefs(baseClass, translationScope, argStack, prefsAssetVersion); + + Debug.initialize(); + } + + /** + * request User's prefSet from the preferenceServlet and return the prefSetXML string. + * + * @author eunyee + * @param prefServlet + * @param translationScope + * TODO + * @param uid + * @return + */ + protected PrefSet requestPrefFromServlet(String prefServlet, SimplTypesScope translationScope) + { + System.out.println("retrieving preferences set from servlet: " + prefServlet); + + try + { + URL url = new URL(prefServlet); + URLConnection connection = url.openConnection(); + + // specify the content type that binary data is sent + connection.setRequestProperty("Content-Type", "text/xml"); + + // define a new BufferedReader on the input stream + BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); + + // receive data from the servlet + String prefSetXML = in.readLine(); + PrefSet prfs = null; + try + { + prfs = PrefSet.loadFromCharSequence(prefSetXML, translationScope); + System.out.println("Prefs loaded From Servlet:: "); + if (prfs != null) + SimplTypesScope.serialize(prfs, System.out, StringFormat.XML); + + System.out.println(" --- End Prefs"); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + in.close(); + + return prfs; + } + catch (IOException e) + { + warning("not a servlet URL: " + prefServlet); + } + return null; + } + + /** + * Load Prefs, if possible + * + * @param baseClass + * @param translationScope + * @param argStack + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + private void processPrefs(Class baseClass, SimplTypesScope translationScope, + Stack argStack, float prefsAssetVersion) throws SIMPLTranslationException + { + LaunchType launchType = LaunchType.ECLIPSE; // current default + + // look for launch method identifier in upper case + String arg = pop(argStack); + + if (arg != null) + { + String uc = arg.toUpperCase(); + if ("JNLP".equals(uc)) + { // tells us how we were launched: e.g., JNLP, ECLIPSE, ... + launchType = LaunchType.JNLP; + } + else if ("STUDIES".equals(uc)) + { + launchType = LaunchType.STUDIES; + } + else + { + // TODO -- recognize JAR here !!! + argStack.push(arg); + } + LAUNCH_TYPE_PREF.setValue(launchType); + } + println("LaunchType = " + launchType); + this.launchType = launchType; + // look for codeBase path + arg = pop(argStack); + + // read perhaps meta-preferences and surely preferences from application data dir + File applicationDir = PropertiesAndDirectories.thisApplicationDir(this); + + ParsedURL applicationDataPURL = new ParsedURL(applicationDir); + prefsPURL = applicationDataPURL.getRelative("preferences/prefs.xml"); + debugA("prefsPURL= " + prefsPURL); + + System.out.println("arg: " + arg); + + switch (launchType) + { + case STUDIES: + case JNLP: + // next arg *should* be code base + if ((arg != null) && arg.endsWith("/")) + { + // JNLP only! (as of now) + // right now this only works for http:// + ParsedURL codeBase = ParsedURL.getAbsolute(arg, "Setting up codebase"); + this.setCodeBase(codeBase); + + // from supplied URL instead of from here + try + { + debugA("Considering prefSet=" + prefSet + "\tprefsPURL=" + prefsPURL); + if (prefSet == null) // Normal Case + { + prefSet = PrefSet.load(prefsPURL, translationScope); + if (prefSet != null) + println("OK: Loaded Prefs from " + prefsPURL); + else + println("No Prefs to load from " + prefsPURL); + } + } + catch (SIMPLTranslationException e) + { + // meta prefs o.k. we can continue + warning("Couldn't load Prefs:"); + e.printTraceOrMessage(this, "Prefs", prefsPURL); + println("\tContinuing."); + } + + debugA("argStack.size() = " + argStack.size()); + if (argStack.size() > 0) + { + String prefSpec = ""; + if (arg.startsWith("http://")) + { + // PreferencesServlet + prefSpec = pop(argStack); + + if (prefSpec != null) + { + // load URLEncoded prefs XML straight from the argument + PrefSet JNLPPrefSet = loadPrefsFromJNLP(prefSpec); + + if (JNLPPrefSet != null) + { + if (prefSet == null) + prefSet = JNLPPrefSet; + else + prefSet.append(JNLPPrefSet); + } + else + { // if we got args straight from jnlp, then continue + if (JNLPPrefSet != null) + prefSpec = pop(argStack); + + if (prefSpec != null) + { + PrefSet servletPrefSet = requestPrefFromServlet(prefSpec, translationScope); + if (servletPrefSet == null) + error("incorrect prefXML string returned from the servlet=" + prefSpec); + else + { + if (prefSet == null) + prefSet = servletPrefSet; + else + prefSet.append(servletPrefSet); + } + } + } + } + } + } + } + else + { + error("No code base argument :-( Can't load preferences."); + } + break; + case ECLIPSE: + case JAR: + // NB: This gets executed even if arg was null! + File localCodeBasePath = deriveLocalFileCodeBase(baseClass); // sets codeBase()! + argStack.push(arg); + + // load the application dir prefs from this machine + // (e.g., c:\Documents and Settings\andruid\Application + // Data\combinFormation\preferences\prefs.xml + // these are the ones that get edited interactively! + + prefSet = PrefSet.load(prefsPURL, translationScope); + if (prefSet != null) + println("Loaded Prefs from: " + prefsPURL); + else + println("No Prefs to load from: " + prefsPURL); + + // now seek the path to an application specific xml preferences file + arg = pop(argStack); + // if (arg == null) + // return; + if (arg != null) + { + // load preferences specific to this invocation + if (arg.endsWith(".xml")) + { + File argPrefsFile = new File(localCodeBasePath, ECLIPSE_PREFS_DIR + arg); + ParsedURL argPrefsPURL = new ParsedURL(argPrefsFile); + try + { + PrefSet argPrefSet = PrefSet.load(argPrefsPURL, translationScope); + + if (argPrefSet != null) + { + println("OK: Loaded Prefs from: " + argPrefsFile); + if (prefSet != null) + prefSet.addPrefSet(argPrefSet); + else + prefSet = argPrefSet; + } + else + { + println(""); + String doesntExist = argPrefsFile.exists() ? "" : "\n\tFile does not exist!!!\n\n"; + println("ERROR: Loading Prefs from: " + argPrefsFile + doesntExist); + } + + } + catch (SIMPLTranslationException e) + { + // meta prefs o.k. we can continue without having loaded Prefs now + e.printTraceOrMessage(this, "Couldn't load Prefs", argPrefsPURL); + println("\tContinuing."); + } + } + else + argStack.push(arg); + } + else + argStack.push(arg); // let the next code handle returning. + break; + } + System.out.println("Printing Prefs:\n"); + try + { + if (prefSet != null) + SimplTypesScope.serialize(prefSet, System.out, StringFormat.XML); + + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + System.out.println("\nPrefs Printed"); + if (prefSet != null) + postProcessPrefs(prefSet); + } + + /** + * Look for pref Ops, if delayed: setup their timers, and also set scope for their ops. + * + * @param prefSet + */ + private void postProcessPrefs(PrefSet prefSet) + { + if (sessionScope == null) + return; + for (Pref pref : prefSet.values()) + if (pref != null) + pref.postLoadHook(sessionScope); + } + + private PrefSet loadPrefsFromJNLP(String prefSpec) + { + PrefSet prefSet = null; + + debugA("loadPrefsFromJNLP()"); + if (prefSpec.startsWith("%3Cpref_set")) + { + try + { + String decodedPrefsXML = URLDecoder.decode(prefSpec, "UTF-8"); + debugA("Loading prefs from JNLP: " + decodedPrefsXML); + +// debugA("TranslationScope: \n"); +// for (ClassDescriptor c : translationScope.getClassDescriptors()) +// { +// debugA(c.toString()); +// } + + prefSet = PrefSet.loadFromCharSequence(decodedPrefsXML, translationScope); + } + catch (UnsupportedEncodingException e) + { + e.printStackTrace(); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + } + return prefSet; + } + + /** + * Get the user.dir property. Form a path from it, ending in slash. See if there is path within + * that that includes the package of baseClass. If so, remove that component from the path. + * + * Form a File from this path, and a ParsedURL from the file. Set codeBase to this ParsedURL. + * + * @param baseClass + * Class of the subclass of this that is the main program that was executed. + * + * @return File that corresponds to the path of the local codeBase. + */ + protected File deriveLocalFileCodeBase(Class baseClass) + { + // setup codeBase + if (baseClass == null) + baseClass = this.getClass(); + + Package basePackage = baseClass.getPackage(); + String packageName = basePackage.getName(); + String packageNameAsPath = packageName.replace('.', Files.sep); + + String pathName = System.getProperty("user.dir") + Files.sep; + File path = new File(pathName); + String pathString = path.getAbsolutePath(); + + int packageIndex = pathString.lastIndexOf(packageNameAsPath); + if (packageIndex != -1) + { + pathString = pathString.substring(0, packageIndex); + path = new File(pathString + Files.sep); + } + + codeBase = new ParsedURL(path); + println("codeBase=" + codeBase); + return path; + } + + /** + * @see ecologylab.appframework.Environment#runtimeEnv() + */ + @Override + public int runtimeEnv() + { + return APPLICATION; + } + + /** + * @see ecologylab.appframework.Environment#status(String) + */ + public void showStatus(String s) + { + System.out.println(s); + } + + /** + * @see ecologylab.appframework.Environment#status(String) + */ + @Override + public void status(String msg) + { + if (msg != null) + showStatus(msg); + } + + /** + * @see ecologylab.appframework.Environment#codeBase() return the path to root of the + */ + @Override + public ParsedURL codeBase() + { + return codeBase; + } + + /** + * @see ecologylab.appframework.Environment#docBase() return the current working directory of the + * application which is "c:\web\code\java\cm" + */ + @Override + public ParsedURL docBase() + { + ParsedURL purl = new ParsedURL(new File(System.getProperty("user.dir"))); + return purl; + } + + public ParsedURL preferencesDir() + { + ParsedURL codeBase = codeBase(); + ParsedURL purl = codeBase.getRelative(ECLIPSE_PREFS_DIR, "forming preferences dir"); + return purl; + } + + /** + * Set the codebase for the application. Should only be done at startup. + */ + public void setCodeBase(ParsedURL codeBase) + { + this.codeBase = codeBase; + } + + protected static T pop(Stack stack) + { + return stack.isEmpty() ? null : stack.pop(); + } + + /** + * Translation space used to parse Preferences for this Application. + * + * @return TranslationSpace in use for parsing Preferences + */ + public SimplTypesScope translationScope() + { + return translationScope; + } + + public DownloadProcessor assetsDownloadProcessor() + { + return new SimpleDownloadProcessor(); + } + + /** + * Remove the Pref from the PrefSet associated with this, and from the global set. + * + * @param key + * @return + */ + public void clearPref(String key) + { + if (prefSet != null) + prefSet.clearPref(key); + } + + /** + * + * @return The set of Prefs associated with this application. + */ + protected PrefSet prefSet() + { + return prefSet; + } + + /** + * Adds otherPrefs to this.prefSet, replacing any entries with the same name. + * + * @param otherPrefs + */ + protected void augmentPrefSet(PrefSet otherPrefs) + { + if (prefSet == null) + { + synchronized (this) + { + if (prefSet == null) + this.prefSet = new PrefSet(); + } + } + + synchronized (prefSet) + { + for (String k : otherPrefs.keySet()) + { + this.prefSet.put(k, otherPrefs.get(k)); + } + } + } + + /** + * TODO Not sure how we can handle this in a non-static way; for now, this version does nothing. + * + * @see ecologylab.appframework.Environment#exit(int) + */ + @Override + public void exit(int code) + { + + } + + /** + * XXX not implemented + * + * @see ecologylab.appframework.Environment#navigate(ecologylab.net.ParsedURL, java.lang.String) + */ + @Override + public void navigate(ParsedURL purl, String frame) + { + + } + + /** + * XXX not implemented + * + * @see ecologylab.appframework.Environment#browser() + */ + @Override + public int browser() + { + return 0; + } + + public boolean isRunningInEclipse() + { + return LaunchType.ECLIPSE == this.launchType; + } + + public boolean isRunningLocalhost() + { + return LaunchType.LOCAL_JNLP == this.launchType; + } + + @Override + public String getApplicationName() + { + return applicationName; + } + + @Override + public boolean hasFirefox() + { + // TODO Auto-generated method stub + return false; + } +} diff --git a/simplCore/src/ecologylab/appframework/ApplicationProperties.java b/simplCore/src/ecologylab/appframework/ApplicationProperties.java index 02a82657..bf5f2f94 100644 --- a/simplCore/src/ecologylab/appframework/ApplicationProperties.java +++ b/simplCore/src/ecologylab/appframework/ApplicationProperties.java @@ -1,17 +1,17 @@ -package ecologylab.appframework; - -import ecologylab.appframework.types.prefs.Pref; - - -/** - * General set of reusable String constants for getting properties from the environment. - * - * @author andruid - * @author blake - */ -public interface ApplicationProperties -extends ApplicationPropertyNames -{ - public static final boolean USE_ASSETS_CACHE = Pref.lookupBoolean("use_assets_cache", true); - -} +package ecologylab.appframework; + +import ecologylab.appframework.types.prefs.Pref; + + +/** + * General set of reusable String constants for getting properties from the environment. + * + * @author andruid + * @author blake + */ +public interface ApplicationProperties +extends ApplicationPropertyNames +{ + public static final boolean USE_ASSETS_CACHE = Pref.lookupBoolean("use_assets_cache", true); + +} diff --git a/simplCore/src/ecologylab/appframework/ApplicationPropertyNames.java b/simplCore/src/ecologylab/appframework/ApplicationPropertyNames.java index 8a27063a..d9dd2ed0 100644 --- a/simplCore/src/ecologylab/appframework/ApplicationPropertyNames.java +++ b/simplCore/src/ecologylab/appframework/ApplicationPropertyNames.java @@ -1,17 +1,17 @@ -package ecologylab.appframework; - -public interface ApplicationPropertyNames -{ - public static final String CODEBASE = "code_base"; - - public static final String FRAME = "frame"; - - public static final String GO_PREFIX = "go_prefix"; - - public static final String PREFERENCES_SET = "preferences_set"; - - public static final String PREFERENCES_SET_ASSET = "preferences_set_asset"; - - public static final String LAUNCH_TYPE = "launch_type"; - -} +package ecologylab.appframework; + +public interface ApplicationPropertyNames +{ + public static final String CODEBASE = "code_base"; + + public static final String FRAME = "frame"; + + public static final String GO_PREFIX = "go_prefix"; + + public static final String PREFERENCES_SET = "preferences_set"; + + public static final String PREFERENCES_SET_ASSET = "preferences_set_asset"; + + public static final String LAUNCH_TYPE = "launch_type"; + +} diff --git a/simplCore/src/ecologylab/appframework/ClassRegistry.java b/simplCore/src/ecologylab/appframework/ClassRegistry.java index 68dd77c7..464294ce 100644 --- a/simplCore/src/ecologylab/appframework/ClassRegistry.java +++ b/simplCore/src/ecologylab/appframework/ClassRegistry.java @@ -1,55 +1,55 @@ -/** - * - */ -package ecologylab.appframework; - -import ecologylab.collections.Scope; - -/** - * - * @author andruid - */ -public class ClassRegistry extends Scope> -{ - - /** - * - */ - public ClassRegistry() - { - super(); - - } - - public U lookupInstance(String key) - { - return getInstance(this.get(key)); - } - - /** - * Get a DocumentType from a generic parameterized Class object. - * - * @param thatClass - * @return - */ - public U getInstance(Class thatClass) - { - U result = null; - if (thatClass != null) - { - try - { - result = thatClass.newInstance(); - } catch (InstantiationException e) - { - e.printStackTrace(); - } catch (IllegalAccessException e) - { - e.printStackTrace(); - } - } - return result; - } - - -} +/** + * + */ +package ecologylab.appframework; + +import ecologylab.collections.Scope; + +/** + * + * @author andruid + */ +public class ClassRegistry extends Scope> +{ + + /** + * + */ + public ClassRegistry() + { + super(); + + } + + public U lookupInstance(String key) + { + return getInstance(this.get(key)); + } + + /** + * Get a DocumentType from a generic parameterized Class object. + * + * @param thatClass + * @return + */ + public U getInstance(Class thatClass) + { + U result = null; + if (thatClass != null) + { + try + { + result = thatClass.newInstance(); + } catch (InstantiationException e) + { + e.printStackTrace(); + } catch (IllegalAccessException e) + { + e.printStackTrace(); + } + } + return result; + } + + +} diff --git a/simplCore/src/ecologylab/appframework/Environment.java b/simplCore/src/ecologylab/appframework/Environment.java index 2978c7c8..0e3a93b2 100644 --- a/simplCore/src/ecologylab/appframework/Environment.java +++ b/simplCore/src/ecologylab/appframework/Environment.java @@ -1,389 +1,389 @@ -/* - * Copyright 1996-2002 by Andruid Kerne. All rights reserved. CONFIDENTIAL. Use is subject to - * license terms. - */ -package ecologylab.appframework; - -import ecologylab.appframework.types.prefs.Pref; -import ecologylab.collections.Scope; -import ecologylab.generic.ConsoleUtils; -import ecologylab.generic.Debug; -import ecologylab.generic.StringTools; -import ecologylab.net.ParsedURL; - -/** - * Provides a mechanism for passing parameters/preferences/properties from diverse runtime - * environments, including applets (via the param tag), applications (via a properties file), and - * sooner or later, servlets. - *

- * - * Cooperative programming: Any class that implements this interface needs to include the - * following line of code at the top of its initialization, in order to make the services provided - * by this Environment interface globally accessible.

- * - *
- * Environment.the.set(this);
- * 
- * - *
- * - * The nested class The serves to keep a global reference to the actual instance of the - * singleton class that implements Environment. (Don't have more than 1 instance that does!) - *

- * The raison d'etre of this interface is first to allow programs to utilize services in a - * uniform way, whether they are applets or applications. The raison d'etre of the nested - * class is to overcome the existence of a single java.applet.Applet instance in the - * runtime environment which provides services that conceptually, one expects to get from a static, - * like java.lang.System. This is a simple mechanism that actually does something quite - * complex, and for complex reasons. - *

- * - * Services are then available globally through syntax such as:

- * - *
- * Environment.the.get().parameter("bgcolor");
- * 
- * - *
- */ -public interface Environment -{ - /** - * Holds a reference to the singleton global instance of {@link Environment Environment}, and - * simple methods for getting and setting this reference. - */ - public class The extends Debug - { - Environment environment; - - /** - * Holds preferences for use in servicing parameter(String) requests. - */ - private final Scope preferencesRegistry = new Scope(); - - float javaVersion = 1.1f; // minimum expected - - boolean javaIsBeta; - - boolean javaIsRC; - - boolean hasXML; - - boolean hasServlet; - - boolean checkedForServlet; - - boolean hasQuicktime; - - boolean checkedForQuicktime; - - boolean hasGL; - - boolean checkedForGL; - - boolean hasAgile2D; - - boolean checkedForAgile2D; - - boolean checkedForMultivalent; - - boolean hasMultivalent; - - boolean checkedForPDFBox; - - boolean hasPDFBox; - - boolean checkedForJTidy; - - boolean hasJTidy; - - String frame; - - public The() - { - String sysJavaVersion = System.getProperty("java.version"); - String floatableJavaVersion = StringTools.remove(sysJavaVersion, '_'); - - int firstDot = floatableJavaVersion.indexOf('.'); - int lastDot = floatableJavaVersion.lastIndexOf('.'); - if (firstDot != lastDot) - { - String toFirstDot = floatableJavaVersion.substring(0, firstDot + 1); - String afterFirstDot = floatableJavaVersion.substring(firstDot + 1); - afterFirstDot = StringTools.remove(afterFirstDot, '.'); - floatableJavaVersion = toFirstDot + afterFirstDot; - } - int dashBeta = floatableJavaVersion.indexOf("-beta"); - int dashRC = floatableJavaVersion.indexOf("-rc"); - - if (dashBeta != -1) - { - floatableJavaVersion = floatableJavaVersion.substring(0, dashBeta); - javaIsBeta = true; - } - else if (dashRC != -1) - { - floatableJavaVersion = floatableJavaVersion.substring(0, dashRC); - javaIsRC = true; - } - try - { - javaVersion = Float.parseFloat(floatableJavaVersion); - } - catch (NumberFormatException e) - { - debug("PROBLEM parsing javaVersion = " + floatableJavaVersion); - e.printStackTrace(); - } - // debug("javaVersion="+ sysJavaVersion+" -> "+ javaVersion); - - if (javaVersion >= 1.4f) - hasXML = true; - else - hasXML = checkFor("org.w3c.dom.Node"); - - // debug("javaVersion=" + javaVersion+" hasXML="+hasXML); - } - - public The(Environment e) - { - set(e); - } - - public void set(Environment e) - { - environment = e; - } - - public Environment get() - { - return environment; - } - - /** - * @return The version of Java we're using. - */ - public float javaVersion() - { - return javaVersion; - } - - /** - * Check to see if we're running on what we consider to be a decent, usable version of Java. For - * 1.5, this means rel 4 or more; for 1.4, it means 1.42_04 or more. - * - * @return true if the Java we're running on is good; false if its crap. - */ - public boolean hasGoodJava() - { - float javaVersion = javaVersion(); - // return (javaVersion >= 1.5004) || ((javaVersion < 1.5) && (javaVersion >= 1.4204)); - // accomodate the retarded scc - return (javaVersion >= 1.5); - } - - public boolean javaIsBeta() - { - return javaIsBeta; - } - - public boolean javaIsReleaseCandidate() - { - return javaIsRC; - } - - public boolean hasQuicktime() - { - if (!checkedForQuicktime) - { - checkedForQuicktime = true; - hasQuicktime = checkFor("quicktime.std.movies.Movie"); - } - return hasQuicktime; - } - - public boolean hasAgile2D() - { - if (!checkedForAgile2D) - { - checkedForAgile2D = true; - hasAgile2D = checkFor("agile2D.AgileJFrame"); - } - return hasAgile2D; - } - - public boolean hasMultivalent() - { - if (!checkedForMultivalent) - { - checkedForMultivalent = true; - hasMultivalent = checkFor("multivalent.std.adaptor.pdf.PDFReader"); - debug("hasMultivalent() = " + hasMultivalent); - if (hasMultivalent) - ConsoleUtils.obtrusiveConsoleOutput("Multivalent Found"); - } - return hasMultivalent; - } - - public boolean hasPDFBox() - { - if (!checkedForPDFBox) - { - checkedForPDFBox = true; - hasPDFBox = checkFor("org.pdfbox.pdmodel.PDDocument"); - debug("hasPDFBox() = " + hasPDFBox); - if (hasPDFBox) - ConsoleUtils.obtrusiveConsoleOutput("PDFBox Found"); - } - return hasPDFBox; - } - - public boolean hasJTidy() - { - if (!checkedForJTidy) - { - checkedForJTidy = true; - hasJTidy = checkFor("org.w3c.tidy.TdNode"); - debug("hasJTidy() = " + hasJTidy); - if (hasJTidy) - ConsoleUtils.obtrusiveConsoleOutput("JTidy Found"); - } - return hasJTidy; - } - - public boolean hasGL() - { - if (!checkedForGL) - { - checkedForGL = true; - hasGL = checkFor("gl4java.awt.GLCanvas"); - } - return hasGL; - } - - public boolean hasXML() - { - return hasXML; - } - - public boolean hasServlet() - { - if (!checkedForServlet) - { - checkedForServlet = true; - hasServlet = checkFor("javax.servlet.http.HttpServlet"); - } - return hasServlet; - } - - public static boolean checkFor(String className) - { - boolean result = false; - try - { - Class.forName(className); - result = true; - } - catch (ClassNotFoundException e) - { - println("Environment.checkFor(" + className + ") caught exception " + e); - // e.printStackTrace(); - } - catch (Error e) - { - println("Environment.checkFor(" + className + ") caught error"); - e.printStackTrace(); - } - return result; - } - - public String frame() - { - String result = frame; - if (result == null) - { - result = Pref.lookupString("frame"); - frame = result; - } - return frame; - } - - /** - * The registry of Preferences for this Environment. - * - * @return registry of Preferences for this Environment. - */ - public Scope preferencesRegistry() - { - return preferencesRegistry; - } - - }; - - /** - * Each running entity (be it an applet or an application), should have one and only one instance - * of an Environment. "the" is that singleton instance. - */ - static final The the = new The(); - - /** - * Find out which java runtime we're operating in. - */ - int runtimeEnv(); - - /** - * Find out which browser we're running in. - */ - int browser(); - - /** - * Show msg in the browser's status bar. - * - * Short form, with for (@link java.cm.applet.Applet#showStatus). Also more robust: avoids - * breaking when msg is null. - */ - public void status(String msg); - - /** - * - * Change type from URL to ParsedURL. - */ - ParsedURL codeBase(); - - /** - * - * Change type from URL to ParsedURL. - */ - ParsedURL docBase(); - - /** - * Called at the end of an invocation. - * - * @param code - * -- 0 for normal. other values are application specific. - */ - void exit(int code); - - public static final int APPLICATION = -1; - - public static final int IE = 0; - - public static final int NS = 1; - - public static final int PLUGIN = 2; - - /** - * Open a document in a web browser. - * - * @param purl - * The address of the web document. - * - * @param frame - * Frame to open it in within the web page. This may or may not be used. - */ - public void navigate(ParsedURL purl, String frame); - - public String getApplicationName(); - - public boolean hasFirefox(); -} +/* + * Copyright 1996-2002 by Andruid Kerne. All rights reserved. CONFIDENTIAL. Use is subject to + * license terms. + */ +package ecologylab.appframework; + +import ecologylab.appframework.types.prefs.Pref; +import ecologylab.collections.Scope; +import ecologylab.generic.ConsoleUtils; +import ecologylab.generic.Debug; +import ecologylab.generic.StringTools; +import ecologylab.net.ParsedURL; + +/** + * Provides a mechanism for passing parameters/preferences/properties from diverse runtime + * environments, including applets (via the param tag), applications (via a properties file), and + * sooner or later, servlets. + *

+ * + * Cooperative programming: Any class that implements this interface needs to include the + * following line of code at the top of its initialization, in order to make the services provided + * by this Environment interface globally accessible.

+ * + *
+ * Environment.the.set(this);
+ * 
+ * + *
+ * + * The nested class The serves to keep a global reference to the actual instance of the + * singleton class that implements Environment. (Don't have more than 1 instance that does!) + *

+ * The raison d'etre of this interface is first to allow programs to utilize services in a + * uniform way, whether they are applets or applications. The raison d'etre of the nested + * class is to overcome the existence of a single java.applet.Applet instance in the + * runtime environment which provides services that conceptually, one expects to get from a static, + * like java.lang.System. This is a simple mechanism that actually does something quite + * complex, and for complex reasons. + *

+ * + * Services are then available globally through syntax such as:

+ * + *
+ * Environment.the.get().parameter("bgcolor");
+ * 
+ * + *
+ */ +public interface Environment +{ + /** + * Holds a reference to the singleton global instance of {@link Environment Environment}, and + * simple methods for getting and setting this reference. + */ + public class The extends Debug + { + Environment environment; + + /** + * Holds preferences for use in servicing parameter(String) requests. + */ + private final Scope preferencesRegistry = new Scope(); + + float javaVersion = 1.1f; // minimum expected + + boolean javaIsBeta; + + boolean javaIsRC; + + boolean hasXML; + + boolean hasServlet; + + boolean checkedForServlet; + + boolean hasQuicktime; + + boolean checkedForQuicktime; + + boolean hasGL; + + boolean checkedForGL; + + boolean hasAgile2D; + + boolean checkedForAgile2D; + + boolean checkedForMultivalent; + + boolean hasMultivalent; + + boolean checkedForPDFBox; + + boolean hasPDFBox; + + boolean checkedForJTidy; + + boolean hasJTidy; + + String frame; + + public The() + { + String sysJavaVersion = System.getProperty("java.version"); + String floatableJavaVersion = StringTools.remove(sysJavaVersion, '_'); + + int firstDot = floatableJavaVersion.indexOf('.'); + int lastDot = floatableJavaVersion.lastIndexOf('.'); + if (firstDot != lastDot) + { + String toFirstDot = floatableJavaVersion.substring(0, firstDot + 1); + String afterFirstDot = floatableJavaVersion.substring(firstDot + 1); + afterFirstDot = StringTools.remove(afterFirstDot, '.'); + floatableJavaVersion = toFirstDot + afterFirstDot; + } + int dashBeta = floatableJavaVersion.indexOf("-beta"); + int dashRC = floatableJavaVersion.indexOf("-rc"); + + if (dashBeta != -1) + { + floatableJavaVersion = floatableJavaVersion.substring(0, dashBeta); + javaIsBeta = true; + } + else if (dashRC != -1) + { + floatableJavaVersion = floatableJavaVersion.substring(0, dashRC); + javaIsRC = true; + } + try + { + javaVersion = Float.parseFloat(floatableJavaVersion); + } + catch (NumberFormatException e) + { + debug("PROBLEM parsing javaVersion = " + floatableJavaVersion); + e.printStackTrace(); + } + // debug("javaVersion="+ sysJavaVersion+" -> "+ javaVersion); + + if (javaVersion >= 1.4f) + hasXML = true; + else + hasXML = checkFor("org.w3c.dom.Node"); + + // debug("javaVersion=" + javaVersion+" hasXML="+hasXML); + } + + public The(Environment e) + { + set(e); + } + + public void set(Environment e) + { + environment = e; + } + + public Environment get() + { + return environment; + } + + /** + * @return The version of Java we're using. + */ + public float javaVersion() + { + return javaVersion; + } + + /** + * Check to see if we're running on what we consider to be a decent, usable version of Java. For + * 1.5, this means rel 4 or more; for 1.4, it means 1.42_04 or more. + * + * @return true if the Java we're running on is good; false if its crap. + */ + public boolean hasGoodJava() + { + float javaVersion = javaVersion(); + // return (javaVersion >= 1.5004) || ((javaVersion < 1.5) && (javaVersion >= 1.4204)); + // accomodate the retarded scc + return (javaVersion >= 1.5); + } + + public boolean javaIsBeta() + { + return javaIsBeta; + } + + public boolean javaIsReleaseCandidate() + { + return javaIsRC; + } + + public boolean hasQuicktime() + { + if (!checkedForQuicktime) + { + checkedForQuicktime = true; + hasQuicktime = checkFor("quicktime.std.movies.Movie"); + } + return hasQuicktime; + } + + public boolean hasAgile2D() + { + if (!checkedForAgile2D) + { + checkedForAgile2D = true; + hasAgile2D = checkFor("agile2D.AgileJFrame"); + } + return hasAgile2D; + } + + public boolean hasMultivalent() + { + if (!checkedForMultivalent) + { + checkedForMultivalent = true; + hasMultivalent = checkFor("multivalent.std.adaptor.pdf.PDFReader"); + debug("hasMultivalent() = " + hasMultivalent); + if (hasMultivalent) + ConsoleUtils.obtrusiveConsoleOutput("Multivalent Found"); + } + return hasMultivalent; + } + + public boolean hasPDFBox() + { + if (!checkedForPDFBox) + { + checkedForPDFBox = true; + hasPDFBox = checkFor("org.pdfbox.pdmodel.PDDocument"); + debug("hasPDFBox() = " + hasPDFBox); + if (hasPDFBox) + ConsoleUtils.obtrusiveConsoleOutput("PDFBox Found"); + } + return hasPDFBox; + } + + public boolean hasJTidy() + { + if (!checkedForJTidy) + { + checkedForJTidy = true; + hasJTidy = checkFor("org.w3c.tidy.TdNode"); + debug("hasJTidy() = " + hasJTidy); + if (hasJTidy) + ConsoleUtils.obtrusiveConsoleOutput("JTidy Found"); + } + return hasJTidy; + } + + public boolean hasGL() + { + if (!checkedForGL) + { + checkedForGL = true; + hasGL = checkFor("gl4java.awt.GLCanvas"); + } + return hasGL; + } + + public boolean hasXML() + { + return hasXML; + } + + public boolean hasServlet() + { + if (!checkedForServlet) + { + checkedForServlet = true; + hasServlet = checkFor("javax.servlet.http.HttpServlet"); + } + return hasServlet; + } + + public static boolean checkFor(String className) + { + boolean result = false; + try + { + Class.forName(className); + result = true; + } + catch (ClassNotFoundException e) + { + println("Environment.checkFor(" + className + ") caught exception " + e); + // e.printStackTrace(); + } + catch (Error e) + { + println("Environment.checkFor(" + className + ") caught error"); + e.printStackTrace(); + } + return result; + } + + public String frame() + { + String result = frame; + if (result == null) + { + result = Pref.lookupString("frame"); + frame = result; + } + return frame; + } + + /** + * The registry of Preferences for this Environment. + * + * @return registry of Preferences for this Environment. + */ + public Scope preferencesRegistry() + { + return preferencesRegistry; + } + + }; + + /** + * Each running entity (be it an applet or an application), should have one and only one instance + * of an Environment. "the" is that singleton instance. + */ + static final The the = new The(); + + /** + * Find out which java runtime we're operating in. + */ + int runtimeEnv(); + + /** + * Find out which browser we're running in. + */ + int browser(); + + /** + * Show msg in the browser's status bar. + * + * Short form, with for (@link java.cm.applet.Applet#showStatus). Also more robust: avoids + * breaking when msg is null. + */ + public void status(String msg); + + /** + * + * Change type from URL to ParsedURL. + */ + ParsedURL codeBase(); + + /** + * + * Change type from URL to ParsedURL. + */ + ParsedURL docBase(); + + /** + * Called at the end of an invocation. + * + * @param code + * -- 0 for normal. other values are application specific. + */ + void exit(int code); + + public static final int APPLICATION = -1; + + public static final int IE = 0; + + public static final int NS = 1; + + public static final int PLUGIN = 2; + + /** + * Open a document in a web browser. + * + * @param purl + * The address of the web document. + * + * @param frame + * Frame to open it in within the web page. This may or may not be used. + */ + public void navigate(ParsedURL purl, String frame); + + public String getApplicationName(); + + public boolean hasFirefox(); +} diff --git a/simplCore/src/ecologylab/appframework/MacOSAppHandler.java b/simplCore/src/ecologylab/appframework/MacOSAppHandler.java index 017229fe..71cc1bdc 100644 --- a/simplCore/src/ecologylab/appframework/MacOSAppHandler.java +++ b/simplCore/src/ecologylab/appframework/MacOSAppHandler.java @@ -1,27 +1,27 @@ -/** - * - */ -package ecologylab.appframework; - -/** - * Interface for handling Mac OS X application specific events (those related to the application menu found only on Mac OS X). - * - * @author andrew - * - */ -public interface MacOSAppHandler -{ - public void handleAbout(); - - public void handleOpenApplication(); - - public void handleOpenFile(String filename); - - public void handlePreferences(); - - public void handlePrintFile(String filename); - - public void handleQuit(); - - public void handleReOpenApplication(); -} +/** + * + */ +package ecologylab.appframework; + +/** + * Interface for handling Mac OS X application specific events (those related to the application menu found only on Mac OS X). + * + * @author andrew + * + */ +public interface MacOSAppHandler +{ + public void handleAbout(); + + public void handleOpenApplication(); + + public void handleOpenFile(String filename); + + public void handlePreferences(); + + public void handlePrintFile(String filename); + + public void handleQuit(); + + public void handleReOpenApplication(); +} diff --git a/simplCore/src/ecologylab/appframework/Memory.java b/simplCore/src/ecologylab/appframework/Memory.java index 500902c1..02584aff 100644 --- a/simplCore/src/ecologylab/appframework/Memory.java +++ b/simplCore/src/ecologylab/appframework/Memory.java @@ -1,192 +1,192 @@ -/* - * Copyright 1996-2002 by Andruid Kerne. All rights reserved. CONFIDENTIAL. Use is subject to - * license terms. - */ -package ecologylab.appframework; - -import ecologylab.generic.Debug; -import ecologylab.generic.StringTools; - -/** - * Utility routines related to memory management, used to watch the JVM's consumption of memory, and - * to kick the garbage collector into action. - */ -public class Memory -{ - // private static final int KICK_GC_COUNT = 5; - private static final int KICK_GC_COUNT = 3; - - /** - * Less than this many bytes of memory free means danger, baby. Currently set at 32M for PC and 0M for ANDROID - */ - - public static final int DANGER_THRESHOLD = (PropertiesAndDirectories.os() == PropertiesAndDirectories.ANDROID) ? 0 - : 32 * 1024 * 1024; - - public static final int RECLAIM_THRESHOLD = 2 * DANGER_THRESHOLD; - - static final Runtime RUNTIME = Runtime.getRuntime(); - - /** - * Number of times we've called gc(). - */ - public static int gcCount; - - public static boolean isMicroshaftVM; - - static long gcTimeStamp; - - static StringBuffer buffy = new StringBuffer(256); - - static final int GC_MAX_DELTA_T = 30 * 1000; // 30 seconds - - /** - * Prod the garbage collector, and print a message about memory status. - */ - public static void reclaim() - { - reclaim(""); - } - - /** - * Prod the garbage collector, and print a message about memory status. - * - * @param s - * Part of the message to be printed, to identify call site. - */ - public static synchronized void reclaim(String s) - { - try - { - StringTools.clear(buffy); - buffy.append("\nMemory.reclaim(").append(Thread.currentThread().getName()).append(s) - .append("):\n\t").append(getFreeMemoryInK()); - reclaimQuiet(); - buffy.append(" -> ").append(usage()).append("\t #").append(gcCount).append("\n"); - Debug.println(buffy); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - public static synchronized void reclaimQuiet() - { - gcTimeStamp = System.currentTimeMillis(); - System.gc(); - gcCount++; - } - - private static final Object MEMORY_RECLAIM_LOCK = new Object(); - - /** - * Try to reclaim memory if it seems to be in low supply. Kicks the garbage collector, perhaps - * repeatedly. Does this even though GC is supposed to be automatic. - *

- * Also maintains the current time stamp to the one in which the garbage collector was last - * kicked. To avoid maxing out the CPU calling GC repeatedly, will not kick GC again if the last - * time was recent. (Currently, recent means within the last 30 seconds.) - * - * @return true if memory status is in danger and more agressive measures are called for. false if - * everything is fine, and the caller can proceed to perform operations that use lots of - * memory, as needed. - * - */ - public static boolean reclaimIfLow() - { - synchronized (MEMORY_RECLAIM_LOCK) - { - // this lock pushes memory check (and the expensive reclaim part) into one thread at a time. - - long now = System.currentTimeMillis(); - long deltaT = now - gcTimeStamp; - if (deltaT >= GC_MAX_DELTA_T) - { - for (int i = 0; i != KICK_GC_COUNT; i++) - { - if (RUNTIME.freeMemory() < RECLAIM_THRESHOLD) - reclaim(); - else - break; - } - } - } - return RUNTIME.freeMemory() < DANGER_THRESHOLD; - } - - public static void recover(Throwable throwable, String msg) - { - Memory.reclaimQuiet(); - Debug.println("Memory.recover()"); - if (msg != null) - Memory.reclaim(msg); - throwable.printStackTrace(); - // Thread.dumpStack(); - Debug.println(Memory.threads()); - Debug.println(""); - } - - public static String usage() - { - return getFreeMemoryInK() + " free of " + K(RUNTIME.totalMemory()); - } - - public static String K(long numBytes) - { - return (numBytes / 1024) + "K"; - } - - public static String threads() - { - Thread current = Thread.currentThread(); - int count = Thread.activeCount(); - Thread[] threads = new Thread[count]; - Thread.enumerate(threads); - String result = count + " Threads ACTIVE\n"; - for (int i = 0; i != count; i++) - { - Thread t = threads[i]; - if (t != null) - { - // String alive = t.isAlive() ? "alive" : "dead"; - result += threads[i].getName() + "\n"; - } - } - return result; - } - - static int outOfMemoryCount; - - static boolean processingOutOfMemory; - - static final int ENOUGH_OUT_OF_MEMORY_CALLS = 10; - - /** - * @return true if its time to give up! - */ - public static boolean outOfMemory(Throwable throwable) - { - if (outOfMemoryCount >= ENOUGH_OUT_OF_MEMORY_CALLS) - return true; - - if (!processingOutOfMemory) - { // dont bother locking, cause we're too desparate - processingOutOfMemory = true; - outOfMemoryCount++; - Memory.recover(throwable, null); - processingOutOfMemory = false; - } - return false; - } - - public static long getFreeMemoryInBytes() - { - return RUNTIME.freeMemory(); - } - - public static String getFreeMemoryInK() - { - return K(getFreeMemoryInBytes()); - } -} +/* + * Copyright 1996-2002 by Andruid Kerne. All rights reserved. CONFIDENTIAL. Use is subject to + * license terms. + */ +package ecologylab.appframework; + +import ecologylab.generic.Debug; +import ecologylab.generic.StringTools; + +/** + * Utility routines related to memory management, used to watch the JVM's consumption of memory, and + * to kick the garbage collector into action. + */ +public class Memory +{ + // private static final int KICK_GC_COUNT = 5; + private static final int KICK_GC_COUNT = 3; + + /** + * Less than this many bytes of memory free means danger, baby. Currently set at 32M for PC and 0M for ANDROID + */ + + public static final int DANGER_THRESHOLD = (PropertiesAndDirectories.os() == PropertiesAndDirectories.ANDROID) ? 0 + : 32 * 1024 * 1024; + + public static final int RECLAIM_THRESHOLD = 2 * DANGER_THRESHOLD; + + static final Runtime RUNTIME = Runtime.getRuntime(); + + /** + * Number of times we've called gc(). + */ + public static int gcCount; + + public static boolean isMicroshaftVM; + + static long gcTimeStamp; + + static StringBuffer buffy = new StringBuffer(256); + + static final int GC_MAX_DELTA_T = 30 * 1000; // 30 seconds + + /** + * Prod the garbage collector, and print a message about memory status. + */ + public static void reclaim() + { + reclaim(""); + } + + /** + * Prod the garbage collector, and print a message about memory status. + * + * @param s + * Part of the message to be printed, to identify call site. + */ + public static synchronized void reclaim(String s) + { + try + { + StringTools.clear(buffy); + buffy.append("\nMemory.reclaim(").append(Thread.currentThread().getName()).append(s) + .append("):\n\t").append(getFreeMemoryInK()); + reclaimQuiet(); + buffy.append(" -> ").append(usage()).append("\t #").append(gcCount).append("\n"); + Debug.println(buffy); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + public static synchronized void reclaimQuiet() + { + gcTimeStamp = System.currentTimeMillis(); + System.gc(); + gcCount++; + } + + private static final Object MEMORY_RECLAIM_LOCK = new Object(); + + /** + * Try to reclaim memory if it seems to be in low supply. Kicks the garbage collector, perhaps + * repeatedly. Does this even though GC is supposed to be automatic. + *

+ * Also maintains the current time stamp to the one in which the garbage collector was last + * kicked. To avoid maxing out the CPU calling GC repeatedly, will not kick GC again if the last + * time was recent. (Currently, recent means within the last 30 seconds.) + * + * @return true if memory status is in danger and more agressive measures are called for. false if + * everything is fine, and the caller can proceed to perform operations that use lots of + * memory, as needed. + * + */ + public static boolean reclaimIfLow() + { + synchronized (MEMORY_RECLAIM_LOCK) + { + // this lock pushes memory check (and the expensive reclaim part) into one thread at a time. + + long now = System.currentTimeMillis(); + long deltaT = now - gcTimeStamp; + if (deltaT >= GC_MAX_DELTA_T) + { + for (int i = 0; i != KICK_GC_COUNT; i++) + { + if (RUNTIME.freeMemory() < RECLAIM_THRESHOLD) + reclaim(); + else + break; + } + } + } + return RUNTIME.freeMemory() < DANGER_THRESHOLD; + } + + public static void recover(Throwable throwable, String msg) + { + Memory.reclaimQuiet(); + Debug.println("Memory.recover()"); + if (msg != null) + Memory.reclaim(msg); + throwable.printStackTrace(); + // Thread.dumpStack(); + Debug.println(Memory.threads()); + Debug.println(""); + } + + public static String usage() + { + return getFreeMemoryInK() + " free of " + K(RUNTIME.totalMemory()); + } + + public static String K(long numBytes) + { + return (numBytes / 1024) + "K"; + } + + public static String threads() + { + Thread current = Thread.currentThread(); + int count = Thread.activeCount(); + Thread[] threads = new Thread[count]; + Thread.enumerate(threads); + String result = count + " Threads ACTIVE\n"; + for (int i = 0; i != count; i++) + { + Thread t = threads[i]; + if (t != null) + { + // String alive = t.isAlive() ? "alive" : "dead"; + result += threads[i].getName() + "\n"; + } + } + return result; + } + + static int outOfMemoryCount; + + static boolean processingOutOfMemory; + + static final int ENOUGH_OUT_OF_MEMORY_CALLS = 10; + + /** + * @return true if its time to give up! + */ + public static boolean outOfMemory(Throwable throwable) + { + if (outOfMemoryCount >= ENOUGH_OUT_OF_MEMORY_CALLS) + return true; + + if (!processingOutOfMemory) + { // dont bother locking, cause we're too desparate + processingOutOfMemory = true; + outOfMemoryCount++; + Memory.recover(throwable, null); + processingOutOfMemory = false; + } + return false; + } + + public static long getFreeMemoryInBytes() + { + return RUNTIME.freeMemory(); + } + + public static String getFreeMemoryInK() + { + return K(getFreeMemoryInBytes()); + } +} diff --git a/simplCore/src/ecologylab/appframework/OutOfMemoryErrorHandler.java b/simplCore/src/ecologylab/appframework/OutOfMemoryErrorHandler.java index a4fd6022..42d5d38c 100644 --- a/simplCore/src/ecologylab/appframework/OutOfMemoryErrorHandler.java +++ b/simplCore/src/ecologylab/appframework/OutOfMemoryErrorHandler.java @@ -1,77 +1,77 @@ -package ecologylab.appframework; - -import java.util.ArrayList; - -import ecologylab.collections.Scope; -import ecologylab.generic.ConsoleUtils; -import ecologylab.generic.Debug; -import ecologylab.generic.ExceptionHandler; - - -/** - * Handle running out of memory. Basically, inform the user, ask if they wish - * to save, then exit combinformation. - * - */ -public class OutOfMemoryErrorHandler -extends Debug -{ - private static ArrayList handlers = new ArrayList(); - private static Scope objectRegistry; - - private static boolean previouslyRanOut = false; - - /** - * The OutOfMemoryError memory threshold (in bytes) that means we should shut down - */ - private static final long OUT_OF_MEMORY_THRESHOLD = 4000000; - - private OutOfMemoryErrorHandler() {} - - public static void registerObjectRegistry(Scope oRegistry) - { - objectRegistry = oRegistry; - } - - /** - * Register an ExceptionHandler for callback when an exception - * is thrown - * @param exceptionHandler The ExceptionHandler to add. - */ - public static void registerHandler(ExceptionHandler exceptionHandler) - { - handlers.add(exceptionHandler); - } - - /** - * Call to register that an exception has ocurred. Results in all - * registered handlers being notified. - * @param e - */ - public static void handleException(OutOfMemoryError e) - { - //in case we get here prematurely - if (Memory.getFreeMemoryInBytes() > OUT_OF_MEMORY_THRESHOLD) - { - ConsoleUtils.obtrusiveConsoleOutput("OutOfMemoryErrorHandler BYPASSED PREMATURE MEMORY ERROR"); - e.printStackTrace(); - return; - } - - //ConsoleUtils.obtrusiveConsoleOutput("Free Memory: " + currentFreeMemory + " bytes"); - //ConsoleUtils.obtrusiveConsoleOutput("Memory Threshold: " + OUT_OF_MEMORY_THRESHOLD + " bytes"); - - //don't bother synchronizing because we're probably hosed and can't do it. - if (previouslyRanOut) //we already handled it - return; - previouslyRanOut = true; - - Debug.println("Calling OUT OF MEMORY Handlers cause: "); - e.printStackTrace(); - for (int i=0; i handlers = new ArrayList(); + private static Scope objectRegistry; + + private static boolean previouslyRanOut = false; + + /** + * The OutOfMemoryError memory threshold (in bytes) that means we should shut down + */ + private static final long OUT_OF_MEMORY_THRESHOLD = 4000000; + + private OutOfMemoryErrorHandler() {} + + public static void registerObjectRegistry(Scope oRegistry) + { + objectRegistry = oRegistry; + } + + /** + * Register an ExceptionHandler for callback when an exception + * is thrown + * @param exceptionHandler The ExceptionHandler to add. + */ + public static void registerHandler(ExceptionHandler exceptionHandler) + { + handlers.add(exceptionHandler); + } + + /** + * Call to register that an exception has ocurred. Results in all + * registered handlers being notified. + * @param e + */ + public static void handleException(OutOfMemoryError e) + { + //in case we get here prematurely + if (Memory.getFreeMemoryInBytes() > OUT_OF_MEMORY_THRESHOLD) + { + ConsoleUtils.obtrusiveConsoleOutput("OutOfMemoryErrorHandler BYPASSED PREMATURE MEMORY ERROR"); + e.printStackTrace(); + return; + } + + //ConsoleUtils.obtrusiveConsoleOutput("Free Memory: " + currentFreeMemory + " bytes"); + //ConsoleUtils.obtrusiveConsoleOutput("Memory Threshold: " + OUT_OF_MEMORY_THRESHOLD + " bytes"); + + //don't bother synchronizing because we're probably hosed and can't do it. + if (previouslyRanOut) //we already handled it + return; + previouslyRanOut = true; + + Debug.println("Calling OUT OF MEMORY Handlers cause: "); + e.printStackTrace(); + for (int i=0; i extends Debug -implements DownloadProcessor -{ - /** - * - */ - public SimpleDownloadProcessor() - { - super(); - } - - /* - * A no-op to conform to the interface spec. We have no threads to stop :-) - */ - @Override - public void stop() - { - } - - /** - * Download it now, in this thread. - * - * @param downloadable - * The thing to download. - * @param dispatchTarget - * Ignored, since we are not asynchronous, there are no callbacks. - */ - // TODO improve error handling here - @Override - public void download(T downloadable, Continuation continuation) - { - try - { - downloadable.performDownload(); - } - catch (IOException e) - { - e.printStackTrace(); - downloadable.handleIoError(e); - } - finally - { - if (continuation != null) - continuation.callback(downloadable); - } - } - - @Override - public void requestStop() - { - // TODO Auto-generated method stub - - } - -} +/** + * + */ +package ecologylab.appframework; + +import java.io.IOException; + +import ecologylab.concurrent.Downloadable; +import ecologylab.generic.Continuation; +import ecologylab.generic.Debug; +import ecologylab.io.DownloadProcessor; + +/** + * A simple download processor: just download the Downloadable immediately. + * + * @author andruid + */ +public class SimpleDownloadProcessor extends Debug +implements DownloadProcessor +{ + /** + * + */ + public SimpleDownloadProcessor() + { + super(); + } + + /* + * A no-op to conform to the interface spec. We have no threads to stop :-) + */ + @Override + public void stop() + { + } + + /** + * Download it now, in this thread. + * + * @param downloadable + * The thing to download. + * @param dispatchTarget + * Ignored, since we are not asynchronous, there are no callbacks. + */ + // TODO improve error handling here + @Override + public void download(T downloadable, Continuation continuation) + { + try + { + downloadable.performDownload(); + } + catch (IOException e) + { + e.printStackTrace(); + downloadable.handleIoError(e); + } + finally + { + if (continuation != null) + continuation.callback(downloadable); + } + } + + @Override + public void requestStop() + { + // TODO Auto-generated method stub + + } + +} diff --git a/simplCore/src/ecologylab/appframework/SingletonApplicationEnvironment.java b/simplCore/src/ecologylab/appframework/SingletonApplicationEnvironment.java index 0fcd6f59..2472775d 100644 --- a/simplCore/src/ecologylab/appframework/SingletonApplicationEnvironment.java +++ b/simplCore/src/ecologylab/appframework/SingletonApplicationEnvironment.java @@ -1,1234 +1,1234 @@ -package ecologylab.appframework; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLDecoder; -import java.util.Stack; - -import ecologylab.appframework.types.prefs.MetaPrefSet; -import ecologylab.appframework.types.prefs.MetaPrefsTranslationScope; -import ecologylab.appframework.types.prefs.Pref; -import ecologylab.appframework.types.prefs.PrefSet; -import ecologylab.collections.Scope; -import ecologylab.generic.Debug; -import ecologylab.io.Assets; -import ecologylab.io.AssetsRoot; -import ecologylab.io.Files; -import ecologylab.net.ParsedURL; -import ecologylab.platformspecifics.FundamentalPlatformSpecifics; -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.XMLTranslationExceptionTypes; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * An instance of Environment, which is an application, rather than an applet, or a servlet. The - * Environment mechanism is used to enable the provision of contextual runtime configuration - * parameter services in a way that is independent of the deployment structure. - * - * The SingletonApplicationEnvironment differs from ApplicationEnvironment in that it sets the - * static Environment.the (among other static references). It CANNOT be used in a situation where - * multiple ApplicationEnvironments will operate in the same JVM. It does, however, simplify the use - * of Prefs and other statically accessed application components. - * - * @author Andruid - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class SingletonApplicationEnvironment extends ApplicationEnvironment implements Environment, - XMLTranslationExceptionTypes, ApplicationPropertyNames -{ - public static final String SCREEN_SIZE = "screen_size"; - - private static final String METAPREFS_XML = "metaprefs.xml"; - - private static boolean inUse = false; - - /** Set of MetaPrefs that describe preferences and provide default values. */ - MetaPrefSet metaPrefSet; - - // must initialize this before subsequent lookup by scope name. - static final SimplTypesScope META_PREFS_TRANSLATION_SCOPE = MetaPrefsTranslationScope.get(); - - public static enum WindowSize - { - PASS_PARAMS, QUARTER_SCREEN, ALMOST_HALF, NEAR_FULL, FULL_SCREEN - } - - public static final String TOP_LEVEL_HEIGHT = "topheight"; - public static final String TOP_LEVEL_WIDTH = "topwidth"; - - static boolean firefoxExists = false; - - /** - * Create an ApplicationEnvironment. Create an empty properties object for application parameters. - *

- * No command line argument is processed. Only default preferences are loaded, and processed with - * the default TranslationSpace. - * - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @throws SIMPLTranslationException - */ - public SingletonApplicationEnvironment(String applicationName) throws SIMPLTranslationException - { - this(null, applicationName, null); - } - - /** - * Create an ApplicationEnvironment. Load preferences from XML file founds in the - * config/preferences directory. Default preferences will be loaded from preferences.xml. If there - * is a 0th command line argument, that is the name of an additional preferences file. - * - * @param applicationName - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - public SingletonApplicationEnvironment( String applicationName, - SimplTypesScope translationScope, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this(applicationName, translationScope, (SimplTypesScope) null, args, prefsAssetVersion); - } - - /** - * Create an ApplicationEnvironment. Load preferences from XML file founds in the - * config/preferences directory. Default preferences will be loaded from preferences.xml. If there - * is a 0th command line argument, that is the name of an additional preferences file. - * - * @param applicationName - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param customPrefs - * TODO - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - public SingletonApplicationEnvironment( String applicationName, - SimplTypesScope translationScope, - Class>[] customPrefs, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this(applicationName, (Scope) null, translationScope, customPrefs, args, prefsAssetVersion); - } - - /** - * - * @param applicationName - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param sessionScope - * @param customPrefs - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * @throws SIMPLTranslationException - */ - public SingletonApplicationEnvironment( String applicationName, - Scope sessionScope, - SimplTypesScope translationScope, - Class>[] customPrefs, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this( (Class) null, - applicationName, - sessionScope, - translationScope, - prefsClassArrayToTranslationScope(customPrefs), - args, - prefsAssetVersion); - } - - /** - * Create an ApplicationEnvironment. Load preferences from XML file founds in the - * config/preferences directory. Default preferences will be loaded from preferences.xml. If there - * is a 0th command line argument, that is the name of an additional preferences file. - * - * @param applicationName - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param customPrefsTranslationScope - * TODO - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - public SingletonApplicationEnvironment( String applicationName, - SimplTypesScope translationScope, - SimplTypesScope customPrefsTranslationScope, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this( (Class) null, - applicationName, - (Scope) null, - translationScope, - customPrefsTranslationScope, - args, - prefsAssetVersion); - } - - /** - * Create an ApplicationEnvironment. Load preferences from XML files found in the - * config/preferences directory. Default preferences will be loaded from preferences.xml. If there - * is a 0th command line argument, that is the name of an additional preferences file. - *

- * The default TranslationSpace, from - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * - * @param applicationName - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @throws SIMPLTranslationException - */ - public SingletonApplicationEnvironment(String applicationName, String args[]) - throws SIMPLTranslationException - { - this(applicationName, (SimplTypesScope) null, (SimplTypesScope) null, args, 0); - } - - /** - * Create an ApplicationEnvironment. Get the base for finding the path to the "codeBase" by using - * the package path of the baseClass passed in. - *

- * Load preferences from XML file founds in the codeBase/config/preferences directory. Default - * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that - * is the name of an additional preferences file. - *

- * Also, sets the Assets cacheRoot to the applicationDir(). - *

- * The default TranslationSpace, from - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * - * @param baseClass - * Used for computing codeBase property. - * @param applicationName - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full - * @throws SIMPLTranslationException - */ - public SingletonApplicationEnvironment(Class baseClass, String applicationName, String args[]) - throws SIMPLTranslationException - { - this(baseClass, applicationName, null, null, null, args, 0); - } - - /** - * Additional constructor to hold the session scope for post processing loaded preferences. - * - * @param applicationName - * @param sessionScope - */ - public SingletonApplicationEnvironment( Class baseClass, - String applicationName, - SimplTypesScope translationScope, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this(baseClass, applicationName, null, translationScope, null, args, prefsAssetVersion); - } - - /** - * Create an ApplicationEnvironment. - *

- * Treats the args array like a stack. If any args are missing (based on their format), they are - * skipped. - *

- * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local - * relative path, or a URL-based absolute path. - *

- * The next possible arg is a preferences file. This ends with .xml. - *

- * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen - * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost - * half; 3; near full; 4 full - *

- * Get the base for finding the path to the "codeBase" by using the package path of the baseClass - * passed in. - *

- * Load preferences from XML file founds in the codeBase/config/preferences directory. Default - * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that - * is the name of an additional preferences file. - *

- * Also, sets the Assets cacheRoot to the applicationDir(). - *

- * The default TranslationSpace, from - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * - * @param baseClass - * Used for computing codeBase property. - * @param applicationName - * Name of the application. - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - public SingletonApplicationEnvironment( Class baseClass, - String applicationName, - Scope sessionScope, - SimplTypesScope translationScope, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - this(baseClass, applicationName, sessionScope, translationScope, null, args, prefsAssetVersion); - } - - /** - * Create an ApplicationEnvironment. - *

- * Treats the args array like a stack. If any args are missing (based on their format), they are - * skipped. - *

- * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local - * relative path, or a URL-based absolute path. - *

- * The next possible arg is a preferences file. This ends with .xml. - *

- * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen - * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost - * half; 3; near full; 4 full - *

- * Get the base for finding the path to the "codeBase" by using the package path of the baseClass - * passed in. - *

- * Load preferences from XML file founds in the codeBase/config/preferences directory. Default - * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that - * is the name of an additional preferences file. - *

- * Also, sets the Assets cacheRoot to the applicationDir(). - *

- * The default TranslationSpace, from - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * - * @param baseClass - * Used for computing codeBase property. - * @param applicationName - * Name of the application. - * @param translationScope - * TranslationSpace used for translating preferences XML. If this is null, - * {@link ecologylab.oodss.messages.DefaultServicesTranslations - * ecologylab.oodss.message.DefaultServicesTranslations} will be used. - * @param customPrefs - * An array of Pref subclasses that are used for this specific application. These classes - * will be automatically composed into a special translation scope used for translating - * prefs for the application. Note that translationScope is NOT used for translating the - * application prefs, but is still required for other translations in the application. - * @param args - * The args array, which is treated as a stack with optional entries. They are: *) JNLP - * -- if that is the launch method *) preferences file if you are running in eclipse. - * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) - * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - public SingletonApplicationEnvironment( Class baseClass, - String applicationName, - Scope sessionScope, - SimplTypesScope translationScope, - SimplTypesScope customPrefsTranslationScope, - String args[], - float prefsAssetVersion) throws SIMPLTranslationException - { - super(baseClass, - applicationName, - sessionScope, - translationScope, - customPrefsTranslationScope, - args, - prefsAssetVersion); - - inUse = true; - - // this is the one and only singleton Environment - Environment.the.set(this); - - PropertiesAndDirectories.setApplicationName(applicationName); - } - - /** - * Sets the applicationName for PropertiesAndDirectories. - * - * @see ecologylab.appframework.ApplicationEnvironment#setApplicationName(java.lang.String) - */ - @Override - protected void setApplicationName(String applicationName) - { - super.setApplicationName(applicationName); - - PropertiesAndDirectories.setApplicationName(applicationName); - } - - @Override - protected void processArgsAndPrefs(Class baseClass, SimplTypesScope translationScope, - float prefsAssetVersion) throws SIMPLTranslationException - { - String arg; - processPrefs(baseClass, translationScope, argStack, prefsAssetVersion); - - Debug.initialize(); - - arg = pop(argStack); - if (arg == null) - return; - try - { - int screenNum = Integer.parseInt(arg); - Pref.useAndSetPrefInt("graphics_device", screenNum); - - } - catch (NumberFormatException e) - { - argStack.push(arg); - } - try - { - arg = pop(argStack); - if (arg == null) - return; - Pref.useAndSetPrefInt(SCREEN_SIZE, WindowSize.valueOf(arg.toUpperCase()).ordinal()); - } - catch (IllegalArgumentException e) - { - argStack.push(arg); - } - if (Pref.lookupInt(SCREEN_SIZE) == 0) - { - try - { - arg = pop(argStack); - if (arg == null) - return; - Pref.useAndSetPrefInt(TOP_LEVEL_WIDTH, Integer.parseInt(arg)); - - arg = pop(argStack); - if (arg == null) - return; - Pref.useAndSetPrefInt(TOP_LEVEL_HEIGHT, Integer.parseInt(arg)); - } - catch (IllegalArgumentException e) - { - argStack.push(arg); - } - } - } - - /** - * request User's prefSet from the preferenceServlet and return the prefSetXML string. - * - * @author eunyee - * @param prefServlet - * @param translationScope - * TODO - * @param uid - * @return - */ - @Override - protected PrefSet requestPrefFromServlet(String prefServlet, SimplTypesScope translationScope) - { - System.out.println("retrieving preferences set from servlet: " + prefServlet); - /* - * try { ParsedURL purl = new ParsedURL(new URL(prefServlet)); - * - * PrefSet prefSet = (PrefSet) ElementState.translateFromXML(purl, PrefTranslations.get()); - * return prefSet; } catch (MalformedURLException e1) { // TODO Auto-generated catch block - * e1.printStackTrace(); } catch (XmlTranslationException e) { // TODO Auto-generated catch - * block e.printStackTrace(); } return null; - */ - try - { - URL url = new URL(prefServlet); - URLConnection connection = url.openConnection(); - - // specify the content type that binary data is sent - connection.setRequestProperty("Content-Type", "text/xml"); - - // define a new BufferedReader on the input stream - BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); - - // receive data from the servlet - String prefSetXML = in.readLine(); - PrefSet prfs = null; - try - { - prfs = PrefSet.loadFromCharSequence(prefSetXML, translationScope); - System.out.println("Prefs loaded From Servlet:: "); - if (prfs != null) - SimplTypesScope.serialize(prfs, System.out, StringFormat.XML); - - System.out.println(" --- End Prefs"); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - in.close(); - - return prfs; - } - catch (IOException e) - { - warning("not a servlet URL: " + prefServlet); - } - return null; - } - - /** - * Load MetaPrefs and Prefs, if possible - * - * @param baseClass - * @param translationScope - * @param argStack - * @param prefsAssetVersion - * TODO - * @throws SIMPLTranslationException - */ - private void processPrefs(Class baseClass, SimplTypesScope translationScope, - Stack argStack, float prefsAssetVersion) throws SIMPLTranslationException - { - LaunchType launchType = LaunchType.ECLIPSE; // current default - - // look for launch method identifier in upper case - String arg = pop(argStack); - - if (arg != null) - { - String uc = arg.toUpperCase(); - if ("JNLP".equals(uc)) - { // tells us how we were launched: e.g., JNLP, ECLIPSE, ... - launchType = LaunchType.JNLP; - } - else if ("STUDIES".equals(uc)) - { - launchType = LaunchType.STUDIES; - } - else - { - // TODO -- recognize JAR here !!! - argStack.push(arg); - } - LAUNCH_TYPE_PREF.setValue(launchType); - } - println("LaunchType = " + launchType); - this.launchType = launchType; - // look for codeBase path - arg = pop(argStack); - - // read perhaps meta-preferences and surely preferences from application data dir - File applicationDir = PropertiesAndDirectories.thisApplicationDir(); - - ParsedURL applicationDataPURL = new ParsedURL(applicationDir); - prefsPURL = applicationDataPURL.getRelative("preferences/prefs.xml"); - debugA("prefsPURL= " + prefsPURL); - - System.out.println("arg: " + arg); - - switch (launchType) - { - case STUDIES: - case JNLP: - // next arg *should* be code base - if ((arg != null) && arg.endsWith("/")) - { - // JNLP only! (as of now) - // right now this only works for http:// - ParsedURL codeBase = ParsedURL.getAbsolute(arg, "Setting up codebase"); - this.setCodeBase(codeBase); - - // XXX is this right? - final String host = codeBase.host(); - if ("localhost".equals(host) || "127.0.0.1".equals(host)) - { - debug("launched from localhost. must be a developer."); - LAUNCH_TYPE_PREF.setValue(LaunchType.LOCAL_JNLP); - } - - SIMPLTranslationException metaPrefSetException = null; - ParsedURL metaPrefsPURL = null; - try - { - AssetsRoot prefAssetsRoot = new AssetsRoot(this, PREFERENCES, null); - File metaPrefsFile = Assets.getAsset( prefAssetsRoot, - METAPREFS_XML, - "prefs", - null, - false, - prefsAssetVersion); - metaPrefsPURL = new ParsedURL(metaPrefsFile); - metaPrefSet = MetaPrefSet.load(metaPrefsFile, translationScope); - println("OK: loaded MetaPrefs from " + metaPrefsFile); - } - catch (SIMPLTranslationException e) - { - metaPrefSetException = e; - } - catch (Exception e) - { - e.printStackTrace(); - } - // from supplied URL instead of from here - try - { - debugA("Considering prefSet=" + prefSet + "\tprefsPURL=" + prefsPURL); - if (prefSet == null) // Normal Case - { - prefSet = PrefSet.load(prefsPURL, translationScope); - if (prefSet != null) - println("OK: Loaded Prefs from " + prefsPURL); - else - println("No Prefs to load from " + prefsPURL); - } - if (metaPrefSetException != null) - { - warning("Couldn't load MetaPrefs:"); - metaPrefSetException.printTraceOrMessage(this, "MetaPrefs", metaPrefsPURL); - println("\tContinuing."); - } - } - catch (SIMPLTranslationException e) - { - if (metaPrefSetException != null) - { - error("Can't load MetaPrefs or Prefs. Quitting."); - metaPrefSetException.printTraceOrMessage(this, "MetaPrefs", metaPrefsPURL); - e.printTraceOrMessage(this, "Prefs", prefsPURL); - } - else - { - // meta prefs o.k. we can continue - warning("Couldn't load Prefs:"); - e.printTraceOrMessage(this, "Prefs", prefsPURL); - println("\tContinuing."); - } - } - - debugA("argStack.size() = " + argStack.size()); - if (argStack.size() > 0) - { - String prefSpec = ""; - if (arg.startsWith("http://")) - { - // PreferencesServlet - prefSpec = pop(argStack); - - if (prefSpec != null) - { - // load URLEncoded prefs XML straight from the argument - PrefSet JNLPPrefSet = loadPrefsFromJNLP(prefSpec); - - if (JNLPPrefSet != null) - { - if (prefSet == null) - prefSet = JNLPPrefSet; - else - prefSet.append(JNLPPrefSet); - } - else - { // if we got args straight from jnlp, then continue - if (JNLPPrefSet != null) - prefSpec = pop(argStack); - - if (prefSpec != null) - { - PrefSet servletPrefSet = requestPrefFromServlet(prefSpec, translationScope); - if (servletPrefSet == null) - error("incorrect prefXML string returned from the servlet=" + prefSpec); - else - { - if (prefSet == null) - prefSet = servletPrefSet; - else - prefSet.append(servletPrefSet); - } - } - } - } - } - } - } - else - { - error("No code base argument :-( Can't load preferences."); - } - break; - case ECLIPSE: - case JAR: - // NB: This gets executed even if arg was null! - File localCodeBasePath = deriveLocalFileCodeBase(baseClass); // sets codeBase()! - argStack.push(arg); - - // AssetsRoot prefAssetsRoot = new AssetsRoot(Assets.getAssetsRoot().getRelative(PREFERENCES), - // Files.newFile(PropertiesAndDirectories.thisApplicationDir(), PREFERENCES)); - // Assets.downloadZip(prefAssetsRoot, "prefs", null, false, prefsAssetVersion); - - SIMPLTranslationException metaPrefSetException = null; - File metaPrefsFile = new File(localCodeBasePath, ECLIPSE_PREFS_DIR + METAPREFS_XML); - ParsedURL metaPrefsPURL = new ParsedURL(metaPrefsFile); - try - { - metaPrefSet = MetaPrefSet.load(metaPrefsPURL, translationScope); - println("OK: Loaded MetaPrefs from: " + metaPrefsFile); - } - catch (SIMPLTranslationException e) - { - metaPrefSetException = e; - } - - // load the application dir prefs from this machine - // (e.g., c:\Documents and Settings\andruid\Application - // Data\combinFormation\preferences\prefs.xml - // these are the ones that get edited interactively! - - prefSet = PrefSet.load(prefsPURL, translationScope); - if (prefSet != null) - println("Loaded Prefs from: " + prefsPURL); - else - println("No Prefs to load from: " + prefsPURL); - - // now seek the path to an application specific xml preferences file - arg = pop(argStack); - // if (arg == null) - // return; - if (arg != null) - { - // load preferences specific to this invocation - if (arg.endsWith(".xml")) - { - File argPrefsFile = new File(localCodeBasePath, ECLIPSE_PREFS_DIR + arg); - ParsedURL argPrefsPURL = new ParsedURL(argPrefsFile); - try - { - PrefSet argPrefSet = PrefSet.load(argPrefsPURL, translationScope); - if (metaPrefSetException != null) - { - warning("Couldn't load MetaPrefs:"); - metaPrefSetException.printTraceOrMessage(this, "MetaPrefs", metaPrefsPURL); - println("\tContinuing."); - } - if (argPrefSet != null) - { - println("OK: Loaded Prefs from: " + argPrefsFile); - if (prefSet != null) - prefSet.addPrefSet(argPrefSet); - else - prefSet = argPrefSet; - } - else - { - println(""); - String doesntExist = argPrefsFile.exists() ? "" : "\n\tFile does not exist!!!\n\n"; - println("ERROR: Loading Prefs from: " + argPrefsFile + doesntExist); - } - - } - catch (SIMPLTranslationException e) - { - if (metaPrefSetException != null) - { - error("Can't load MetaPrefs or Prefs. Quitting."); - metaPrefSetException.printTraceOrMessage(this, "MetaPrefs", metaPrefsPURL); - e.printStackTrace(); - throw e; - } - // meta prefs o.k. we can continue without having loaded Prefs now - e.printTraceOrMessage(this, "Couldn't load Prefs", argPrefsPURL); - println("\tContinuing."); - } - } - else - argStack.push(arg); - } - else - argStack.push(arg); // let the next code handle returning. - break; - } - System.out.println("Printing Prefs:\n"); - try - { - if (prefSet != null) - SimplTypesScope.serialize(prefSet, System.out, StringFormat.XML); - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - System.out.println("\nPrefs Printed"); - if (prefSet != null) - postProcessPrefs(prefSet); - } - - /** - * Look for pref Ops, if delayed: setup their timers, and also set scope for their ops. - * - * @param prefSet - */ - private void postProcessPrefs(PrefSet prefSet) - { - if (sessionScope == null) - return; - for (Pref pref : prefSet.values()) - if (pref != null) - pref.postLoadHook(sessionScope); - } - - private PrefSet loadPrefsFromJNLP(String prefSpec) - { - PrefSet prefSet = null; - - debugA("loadPrefsFromJNLP()"); - if (prefSpec.startsWith("%3Cpref_set")) - { - try - { - String decodedPrefsXML = URLDecoder.decode(prefSpec, "UTF-8"); - debugA("Loading prefs from JNLP: " + decodedPrefsXML); - - for (ClassDescriptor c : translationScope.getClassDescriptors()) - { - debugA(c.toString()); - } - - prefSet = PrefSet.loadFromCharSequence(decodedPrefsXML, translationScope); - } - catch (UnsupportedEncodingException e) - { - e.printStackTrace(); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - } - return prefSet; - } - - /** - * Get the user.dir property. Form a path from it, ending in slash. See if there is path within - * that that includes the package of baseClass. If so, remove that component from the path. - * - * Form a File from this path, and a ParsedURL from the file. Set codeBase to this ParsedURL. - * - * @param baseClass - * Class of the subclass of this that is the main program that was executed. - * - * @return File that corresponds to the path of the local codeBase. - */ - @Override - protected File deriveLocalFileCodeBase(Class baseClass) - { - // setup codeBase - if (baseClass == null) - baseClass = this.getClass(); - - Package basePackage = baseClass.getPackage(); - String packageName = basePackage.getName(); - String packageNameAsPath = packageName.replace('.', Files.sep); - - String pathName = System.getProperty("user.dir") + Files.sep; - File path = new File(pathName); - String pathString = path.getAbsolutePath(); - - // println("looking for " + packageNameAsPath +" in " + pathString); - - int packageIndex = pathString.lastIndexOf(packageNameAsPath); - if (packageIndex != -1) - { - pathString = pathString.substring(0, packageIndex); - path = new File(pathString + Files.sep); - } - - codeBase = new ParsedURL(path); - println("codeBase=" + codeBase); - return path; - } - - /** - * @see ecologylab.appframework.Environment#runtimeEnv() - */ - @Override - public int runtimeEnv() - { - return APPLICATION; - } - - /** - * @see ecologylab.appframework.Environment#status(String) - */ - @Override - public void showStatus(String s) - { - System.out.println(s); - } - - /** - * @see ecologylab.appframework.Environment#status(String) - */ - @Override - public void status(String msg) - { - if (msg != null) - showStatus(msg); - } - - /** - * @see ecologylab.appframework.Environment#docBase() return the current working directory of the - * application which is "c:\web\code\java\cm" - */ - @Override - public ParsedURL docBase() - { - ParsedURL purl = new ParsedURL(new File(System.getProperty("user.dir"))); - return purl; - } - - @Override - public ParsedURL preferencesDir() - { - ParsedURL codeBase = codeBase(); - ParsedURL purl = codeBase.getRelative(ECLIPSE_PREFS_DIR, "forming preferences dir"); - return purl; - } - - static final String FIREFOX_PATH_WINDOWS = "C:\\Program Files\\Mozilla Firefox\\firefox.exe"; - - static final String FIREFOX_PATH_WINDOWS_64 = "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe"; - - static final String FIREFOX_PATH_VIRT = "C:\\Program Files (x86)\\Microsoft Application Virtualization Client\\sfttray.exe"; - - // TODO -- use "open" on the mac!!! - static final String FIREFOX_PATH_MAC = "/Applications/Firefox.app/Contents/MacOS/firefox"; - - // static final String FIREFOX_PATH_MAC = null; - static final String SAFARI_PATH_MAC = "/Applications/Safari.app/Contents/MacOS/Safari"; - - static final String FIREFOX_PATH_LINUX = "/usr/bin/firefox"; - - static final String IE_PATH_WINDOWS = "C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE"; - - static String browserPath; - - /** - * Get the operating system dependent path to a suitable web browser for navigating to a web page. - * This is also dependent on what web browser(s) the user has installed. In particular, we use - * Firefox if it is in its normal place! - * - * @return String that specifies the OS and browser-specific command. - */ - static String getBrowserPath() - { - int os = PropertiesAndDirectories.os(); - String result = browserPath; - if (result == null) - { - switch (os) - { - case PropertiesAndDirectories.XP: - case PropertiesAndDirectories.VISTA_AND_7: - if (!Pref.lookupBoolean("navigate_with_ie")) - result = FIREFOX_PATH_WINDOWS; - if (result != null) - { - File existentialTester = new File(result); - if (!existentialTester.exists()) - { - result = FIREFOX_PATH_WINDOWS_64; - existentialTester = new File(result); - if (!existentialTester.exists()) - { - result = IE_PATH_WINDOWS; - existentialTester = new File(result); - if (!existentialTester.exists()) - result = null; - } - } - } - break; - case PropertiesAndDirectories.MAC: - result = "/usr/bin/open"; - break; - default: - error(PropertiesAndDirectories.getOsName(), "go(ParsedURL) not supported"); - break; - } - if (result != null) - { - browserPath = result; - } - } - return result; - } - - static String[] cachedNavigateArgs; - - /** - * Get the operating system dependent path to a suitable web browser for navigating to a web page. - * This is also dependent on what web browser(s) the user has installed. In particular, we use - * Firefox if it is in its normal place! - * - * @return String that specifies the OS and browser-specific command. - */ - static String[] getNavigateArgs() - { - int os = PropertiesAndDirectories.os(); - String[] result = cachedNavigateArgs; - if (result == null) - { - switch (os) - { - case PropertiesAndDirectories.XP: - case PropertiesAndDirectories.VISTA_AND_7: - String path = null; - if (!Pref.lookupBoolean("navigate_with_ie")) - path = FIREFOX_PATH_WINDOWS; - if (path != null) - { - File existentialTester = new File(path); - firefoxExists = existentialTester.exists(); - if (!firefoxExists) - { - path = FIREFOX_PATH_WINDOWS_64; - existentialTester = new File(path); - firefoxExists = existentialTester.exists(); - } - if (firefoxExists) - { // cool! firefox - result = new String[3]; - result[0] = path; - result[1] = "-new-tab"; - } else { - //Use the SCC Virtualization Path - path = FIREFOX_PATH_VIRT; - existentialTester = new File(path); - firefoxExists = existentialTester.exists(); - if(firefoxExists) - { - result = new String[5]; - result[0] = path; - result[1] = "/launch"; - result[2] = "\"Mozilla Firefox 11\""; - result[3] = "-new-tab"; - } - } - - } - if (result == null) - { - path = IE_PATH_WINDOWS; - File existentialTester = new File(path); - if (existentialTester.exists()) - { - result = new String[2]; - result[0] = path; - } - } - break; - case PropertiesAndDirectories.MAC: - result = new String[4]; - result[0] = "/usr/bin/open"; - result[1] = "-a"; - result[2] = "firefox"; - firefoxExists = true; - break; - case PropertiesAndDirectories.LINUX: - result = new String[2]; - result[0] = FIREFOX_PATH_LINUX; - firefoxExists = true; - break; - default: - error(PropertiesAndDirectories.getOsName(), "go(ParsedURL) not supported"); - break; - } - if (result != null) - { - cachedNavigateArgs = result; - } - } - return result; - } - - - /** - * Returns true if firefox was found on this system. - * @return - */ - @Override - public boolean hasFirefox() - { - getNavigateArgs();//sets firefoxExists if true - return firefoxExists; - } - - - /** - * Navigate to the purl using the best browser we can find. - * - * @param purl - * @param frame - */ - @Override - public void navigate(ParsedURL purl, String frame) - { - String[] navigateArgs = getNavigateArgs(); - if (navigateArgs != null && purl != null) - { - String purlString = purl.toString(); - int numArgs = navigateArgs.length; - navigateArgs[numArgs - 1] = purlString; - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < numArgs; i++) - sb.append(navigateArgs[i]).append(' '); - Debug.println("navigate: " + sb); - try - { - Process p = Runtime.getRuntime().exec(navigateArgs); - } - catch (IOException e) - { - error("navigate() - caught exception: "); - e.printStackTrace(); - } - } - else - error("navigate() - Can't find browser to navigate to."); - } - - @Override - public int browser() - { - return APPLICATION; - } - - /** - * Called at the end of an invocation. Calls System.exit(code). - * - * @param code - * -- 0 for normal. other values are application specific. - */ - @Override - public void exit(int code) - { - System.exit(code); - } - - public static boolean isInUse() - { - return inUse; - } - - public static boolean runningInEclipse() - { - return LaunchType.ECLIPSE == LAUNCH_TYPE_PREF.value(); - } - - public static boolean runningLocalhost() - { - return LaunchType.LOCAL_JNLP == LAUNCH_TYPE_PREF.value(); - } - - /** - * Create and show an editor for preferences, iff the MetaPrefSet and PrefSet are non-null. If the - * PrefSet is null, a new empty one will be created for the editor to use. - * - * @return - */ - public Object createPrefsEditor(final boolean createJFrame, final boolean isStandalone) - { - Object result = null; - if (metaPrefSet != null) - { - if (prefSet == null) - prefSet = new PrefSet(); - result = FundamentalPlatformSpecifics.get().getOrCreatePrefsEditor(metaPrefSet, prefSet, prefsPURL, createJFrame, isStandalone); - } - return result; - } - - /** - * Create and show an editor for preferences, iff the MetaPrefSet and PrefSet are non-null. If the - * PrefSet is null, a new empty one will be created for the editor to use. - * - * @return - */ - public Object createPrefsEditor() - { - return this.createPrefsEditor(true, false); - } - - /** - * - * @return MetaPrefSet for this application, loaded from standard locations. - */ - protected MetaPrefSet metaPrefSet() - { - return metaPrefSet; - } - - @Override - public String getApplicationName() - { - return PropertiesAndDirectories.applicationName; - } -} +package ecologylab.appframework; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLDecoder; +import java.util.Stack; + +import ecologylab.appframework.types.prefs.MetaPrefSet; +import ecologylab.appframework.types.prefs.MetaPrefsTranslationScope; +import ecologylab.appframework.types.prefs.Pref; +import ecologylab.appframework.types.prefs.PrefSet; +import ecologylab.collections.Scope; +import ecologylab.generic.Debug; +import ecologylab.io.Assets; +import ecologylab.io.AssetsRoot; +import ecologylab.io.Files; +import ecologylab.net.ParsedURL; +import ecologylab.platformspecifics.FundamentalPlatformSpecifics; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.XMLTranslationExceptionTypes; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * An instance of Environment, which is an application, rather than an applet, or a servlet. The + * Environment mechanism is used to enable the provision of contextual runtime configuration + * parameter services in a way that is independent of the deployment structure. + * + * The SingletonApplicationEnvironment differs from ApplicationEnvironment in that it sets the + * static Environment.the (among other static references). It CANNOT be used in a situation where + * multiple ApplicationEnvironments will operate in the same JVM. It does, however, simplify the use + * of Prefs and other statically accessed application components. + * + * @author Andruid + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class SingletonApplicationEnvironment extends ApplicationEnvironment implements Environment, + XMLTranslationExceptionTypes, ApplicationPropertyNames +{ + public static final String SCREEN_SIZE = "screen_size"; + + private static final String METAPREFS_XML = "metaprefs.xml"; + + private static boolean inUse = false; + + /** Set of MetaPrefs that describe preferences and provide default values. */ + MetaPrefSet metaPrefSet; + + // must initialize this before subsequent lookup by scope name. + static final SimplTypesScope META_PREFS_TRANSLATION_SCOPE = MetaPrefsTranslationScope.get(); + + public static enum WindowSize + { + PASS_PARAMS, QUARTER_SCREEN, ALMOST_HALF, NEAR_FULL, FULL_SCREEN + } + + public static final String TOP_LEVEL_HEIGHT = "topheight"; + public static final String TOP_LEVEL_WIDTH = "topwidth"; + + static boolean firefoxExists = false; + + /** + * Create an ApplicationEnvironment. Create an empty properties object for application parameters. + *

+ * No command line argument is processed. Only default preferences are loaded, and processed with + * the default TranslationSpace. + * + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @throws SIMPLTranslationException + */ + public SingletonApplicationEnvironment(String applicationName) throws SIMPLTranslationException + { + this(null, applicationName, null); + } + + /** + * Create an ApplicationEnvironment. Load preferences from XML file founds in the + * config/preferences directory. Default preferences will be loaded from preferences.xml. If there + * is a 0th command line argument, that is the name of an additional preferences file. + * + * @param applicationName + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + public SingletonApplicationEnvironment( String applicationName, + SimplTypesScope translationScope, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this(applicationName, translationScope, (SimplTypesScope) null, args, prefsAssetVersion); + } + + /** + * Create an ApplicationEnvironment. Load preferences from XML file founds in the + * config/preferences directory. Default preferences will be loaded from preferences.xml. If there + * is a 0th command line argument, that is the name of an additional preferences file. + * + * @param applicationName + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param customPrefs + * TODO + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + public SingletonApplicationEnvironment( String applicationName, + SimplTypesScope translationScope, + Class>[] customPrefs, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this(applicationName, (Scope) null, translationScope, customPrefs, args, prefsAssetVersion); + } + + /** + * + * @param applicationName + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param sessionScope + * @param customPrefs + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * @throws SIMPLTranslationException + */ + public SingletonApplicationEnvironment( String applicationName, + Scope sessionScope, + SimplTypesScope translationScope, + Class>[] customPrefs, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this( (Class) null, + applicationName, + sessionScope, + translationScope, + prefsClassArrayToTranslationScope(customPrefs), + args, + prefsAssetVersion); + } + + /** + * Create an ApplicationEnvironment. Load preferences from XML file founds in the + * config/preferences directory. Default preferences will be loaded from preferences.xml. If there + * is a 0th command line argument, that is the name of an additional preferences file. + * + * @param applicationName + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param customPrefsTranslationScope + * TODO + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + public SingletonApplicationEnvironment( String applicationName, + SimplTypesScope translationScope, + SimplTypesScope customPrefsTranslationScope, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this( (Class) null, + applicationName, + (Scope) null, + translationScope, + customPrefsTranslationScope, + args, + prefsAssetVersion); + } + + /** + * Create an ApplicationEnvironment. Load preferences from XML files found in the + * config/preferences directory. Default preferences will be loaded from preferences.xml. If there + * is a 0th command line argument, that is the name of an additional preferences file. + *

+ * The default TranslationSpace, from + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * + * @param applicationName + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @throws SIMPLTranslationException + */ + public SingletonApplicationEnvironment(String applicationName, String args[]) + throws SIMPLTranslationException + { + this(applicationName, (SimplTypesScope) null, (SimplTypesScope) null, args, 0); + } + + /** + * Create an ApplicationEnvironment. Get the base for finding the path to the "codeBase" by using + * the package path of the baseClass passed in. + *

+ * Load preferences from XML file founds in the codeBase/config/preferences directory. Default + * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that + * is the name of an additional preferences file. + *

+ * Also, sets the Assets cacheRoot to the applicationDir(). + *

+ * The default TranslationSpace, from + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * + * @param baseClass + * Used for computing codeBase property. + * @param applicationName + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full + * @throws SIMPLTranslationException + */ + public SingletonApplicationEnvironment(Class baseClass, String applicationName, String args[]) + throws SIMPLTranslationException + { + this(baseClass, applicationName, null, null, null, args, 0); + } + + /** + * Additional constructor to hold the session scope for post processing loaded preferences. + * + * @param applicationName + * @param sessionScope + */ + public SingletonApplicationEnvironment( Class baseClass, + String applicationName, + SimplTypesScope translationScope, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this(baseClass, applicationName, null, translationScope, null, args, prefsAssetVersion); + } + + /** + * Create an ApplicationEnvironment. + *

+ * Treats the args array like a stack. If any args are missing (based on their format), they are + * skipped. + *

+ * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local + * relative path, or a URL-based absolute path. + *

+ * The next possible arg is a preferences file. This ends with .xml. + *

+ * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen + * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost + * half; 3; near full; 4 full + *

+ * Get the base for finding the path to the "codeBase" by using the package path of the baseClass + * passed in. + *

+ * Load preferences from XML file founds in the codeBase/config/preferences directory. Default + * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that + * is the name of an additional preferences file. + *

+ * Also, sets the Assets cacheRoot to the applicationDir(). + *

+ * The default TranslationSpace, from + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * + * @param baseClass + * Used for computing codeBase property. + * @param applicationName + * Name of the application. + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + public SingletonApplicationEnvironment( Class baseClass, + String applicationName, + Scope sessionScope, + SimplTypesScope translationScope, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + this(baseClass, applicationName, sessionScope, translationScope, null, args, prefsAssetVersion); + } + + /** + * Create an ApplicationEnvironment. + *

+ * Treats the args array like a stack. If any args are missing (based on their format), they are + * skipped. + *

+ * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local + * relative path, or a URL-based absolute path. + *

+ * The next possible arg is a preferences file. This ends with .xml. + *

+ * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen + * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost + * half; 3; near full; 4 full + *

+ * Get the base for finding the path to the "codeBase" by using the package path of the baseClass + * passed in. + *

+ * Load preferences from XML file founds in the codeBase/config/preferences directory. Default + * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that + * is the name of an additional preferences file. + *

+ * Also, sets the Assets cacheRoot to the applicationDir(). + *

+ * The default TranslationSpace, from + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * + * @param baseClass + * Used for computing codeBase property. + * @param applicationName + * Name of the application. + * @param translationScope + * TranslationSpace used for translating preferences XML. If this is null, + * {@link ecologylab.oodss.messages.DefaultServicesTranslations + * ecologylab.oodss.message.DefaultServicesTranslations} will be used. + * @param customPrefs + * An array of Pref subclasses that are used for this specific application. These classes + * will be automatically composed into a special translation scope used for translating + * prefs for the application. Note that translationScope is NOT used for translating the + * application prefs, but is still required for other translations in the application. + * @param args + * The args array, which is treated as a stack with optional entries. They are: *) JNLP + * -- if that is the launch method *) preferences file if you are running in eclipse. + * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) + * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + public SingletonApplicationEnvironment( Class baseClass, + String applicationName, + Scope sessionScope, + SimplTypesScope translationScope, + SimplTypesScope customPrefsTranslationScope, + String args[], + float prefsAssetVersion) throws SIMPLTranslationException + { + super(baseClass, + applicationName, + sessionScope, + translationScope, + customPrefsTranslationScope, + args, + prefsAssetVersion); + + inUse = true; + + // this is the one and only singleton Environment + Environment.the.set(this); + + PropertiesAndDirectories.setApplicationName(applicationName); + } + + /** + * Sets the applicationName for PropertiesAndDirectories. + * + * @see ecologylab.appframework.ApplicationEnvironment#setApplicationName(java.lang.String) + */ + @Override + protected void setApplicationName(String applicationName) + { + super.setApplicationName(applicationName); + + PropertiesAndDirectories.setApplicationName(applicationName); + } + + @Override + protected void processArgsAndPrefs(Class baseClass, SimplTypesScope translationScope, + float prefsAssetVersion) throws SIMPLTranslationException + { + String arg; + processPrefs(baseClass, translationScope, argStack, prefsAssetVersion); + + Debug.initialize(); + + arg = pop(argStack); + if (arg == null) + return; + try + { + int screenNum = Integer.parseInt(arg); + Pref.useAndSetPrefInt("graphics_device", screenNum); + + } + catch (NumberFormatException e) + { + argStack.push(arg); + } + try + { + arg = pop(argStack); + if (arg == null) + return; + Pref.useAndSetPrefInt(SCREEN_SIZE, WindowSize.valueOf(arg.toUpperCase()).ordinal()); + } + catch (IllegalArgumentException e) + { + argStack.push(arg); + } + if (Pref.lookupInt(SCREEN_SIZE) == 0) + { + try + { + arg = pop(argStack); + if (arg == null) + return; + Pref.useAndSetPrefInt(TOP_LEVEL_WIDTH, Integer.parseInt(arg)); + + arg = pop(argStack); + if (arg == null) + return; + Pref.useAndSetPrefInt(TOP_LEVEL_HEIGHT, Integer.parseInt(arg)); + } + catch (IllegalArgumentException e) + { + argStack.push(arg); + } + } + } + + /** + * request User's prefSet from the preferenceServlet and return the prefSetXML string. + * + * @author eunyee + * @param prefServlet + * @param translationScope + * TODO + * @param uid + * @return + */ + @Override + protected PrefSet requestPrefFromServlet(String prefServlet, SimplTypesScope translationScope) + { + System.out.println("retrieving preferences set from servlet: " + prefServlet); + /* + * try { ParsedURL purl = new ParsedURL(new URL(prefServlet)); + * + * PrefSet prefSet = (PrefSet) ElementState.translateFromXML(purl, PrefTranslations.get()); + * return prefSet; } catch (MalformedURLException e1) { // TODO Auto-generated catch block + * e1.printStackTrace(); } catch (XmlTranslationException e) { // TODO Auto-generated catch + * block e.printStackTrace(); } return null; + */ + try + { + URL url = new URL(prefServlet); + URLConnection connection = url.openConnection(); + + // specify the content type that binary data is sent + connection.setRequestProperty("Content-Type", "text/xml"); + + // define a new BufferedReader on the input stream + BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); + + // receive data from the servlet + String prefSetXML = in.readLine(); + PrefSet prfs = null; + try + { + prfs = PrefSet.loadFromCharSequence(prefSetXML, translationScope); + System.out.println("Prefs loaded From Servlet:: "); + if (prfs != null) + SimplTypesScope.serialize(prfs, System.out, StringFormat.XML); + + System.out.println(" --- End Prefs"); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + in.close(); + + return prfs; + } + catch (IOException e) + { + warning("not a servlet URL: " + prefServlet); + } + return null; + } + + /** + * Load MetaPrefs and Prefs, if possible + * + * @param baseClass + * @param translationScope + * @param argStack + * @param prefsAssetVersion + * TODO + * @throws SIMPLTranslationException + */ + private void processPrefs(Class baseClass, SimplTypesScope translationScope, + Stack argStack, float prefsAssetVersion) throws SIMPLTranslationException + { + LaunchType launchType = LaunchType.ECLIPSE; // current default + + // look for launch method identifier in upper case + String arg = pop(argStack); + + if (arg != null) + { + String uc = arg.toUpperCase(); + if ("JNLP".equals(uc)) + { // tells us how we were launched: e.g., JNLP, ECLIPSE, ... + launchType = LaunchType.JNLP; + } + else if ("STUDIES".equals(uc)) + { + launchType = LaunchType.STUDIES; + } + else + { + // TODO -- recognize JAR here !!! + argStack.push(arg); + } + LAUNCH_TYPE_PREF.setValue(launchType); + } + println("LaunchType = " + launchType); + this.launchType = launchType; + // look for codeBase path + arg = pop(argStack); + + // read perhaps meta-preferences and surely preferences from application data dir + File applicationDir = PropertiesAndDirectories.thisApplicationDir(); + + ParsedURL applicationDataPURL = new ParsedURL(applicationDir); + prefsPURL = applicationDataPURL.getRelative("preferences/prefs.xml"); + debugA("prefsPURL= " + prefsPURL); + + System.out.println("arg: " + arg); + + switch (launchType) + { + case STUDIES: + case JNLP: + // next arg *should* be code base + if ((arg != null) && arg.endsWith("/")) + { + // JNLP only! (as of now) + // right now this only works for http:// + ParsedURL codeBase = ParsedURL.getAbsolute(arg, "Setting up codebase"); + this.setCodeBase(codeBase); + + // XXX is this right? + final String host = codeBase.host(); + if ("localhost".equals(host) || "127.0.0.1".equals(host)) + { + debug("launched from localhost. must be a developer."); + LAUNCH_TYPE_PREF.setValue(LaunchType.LOCAL_JNLP); + } + + SIMPLTranslationException metaPrefSetException = null; + ParsedURL metaPrefsPURL = null; + try + { + AssetsRoot prefAssetsRoot = new AssetsRoot(this, PREFERENCES, null); + File metaPrefsFile = Assets.getAsset( prefAssetsRoot, + METAPREFS_XML, + "prefs", + null, + false, + prefsAssetVersion); + metaPrefsPURL = new ParsedURL(metaPrefsFile); + metaPrefSet = MetaPrefSet.load(metaPrefsFile, translationScope); + println("OK: loaded MetaPrefs from " + metaPrefsFile); + } + catch (SIMPLTranslationException e) + { + metaPrefSetException = e; + } + catch (Exception e) + { + e.printStackTrace(); + } + // from supplied URL instead of from here + try + { + debugA("Considering prefSet=" + prefSet + "\tprefsPURL=" + prefsPURL); + if (prefSet == null) // Normal Case + { + prefSet = PrefSet.load(prefsPURL, translationScope); + if (prefSet != null) + println("OK: Loaded Prefs from " + prefsPURL); + else + println("No Prefs to load from " + prefsPURL); + } + if (metaPrefSetException != null) + { + warning("Couldn't load MetaPrefs:"); + metaPrefSetException.printTraceOrMessage(this, "MetaPrefs", metaPrefsPURL); + println("\tContinuing."); + } + } + catch (SIMPLTranslationException e) + { + if (metaPrefSetException != null) + { + error("Can't load MetaPrefs or Prefs. Quitting."); + metaPrefSetException.printTraceOrMessage(this, "MetaPrefs", metaPrefsPURL); + e.printTraceOrMessage(this, "Prefs", prefsPURL); + } + else + { + // meta prefs o.k. we can continue + warning("Couldn't load Prefs:"); + e.printTraceOrMessage(this, "Prefs", prefsPURL); + println("\tContinuing."); + } + } + + debugA("argStack.size() = " + argStack.size()); + if (argStack.size() > 0) + { + String prefSpec = ""; + if (arg.startsWith("http://")) + { + // PreferencesServlet + prefSpec = pop(argStack); + + if (prefSpec != null) + { + // load URLEncoded prefs XML straight from the argument + PrefSet JNLPPrefSet = loadPrefsFromJNLP(prefSpec); + + if (JNLPPrefSet != null) + { + if (prefSet == null) + prefSet = JNLPPrefSet; + else + prefSet.append(JNLPPrefSet); + } + else + { // if we got args straight from jnlp, then continue + if (JNLPPrefSet != null) + prefSpec = pop(argStack); + + if (prefSpec != null) + { + PrefSet servletPrefSet = requestPrefFromServlet(prefSpec, translationScope); + if (servletPrefSet == null) + error("incorrect prefXML string returned from the servlet=" + prefSpec); + else + { + if (prefSet == null) + prefSet = servletPrefSet; + else + prefSet.append(servletPrefSet); + } + } + } + } + } + } + } + else + { + error("No code base argument :-( Can't load preferences."); + } + break; + case ECLIPSE: + case JAR: + // NB: This gets executed even if arg was null! + File localCodeBasePath = deriveLocalFileCodeBase(baseClass); // sets codeBase()! + argStack.push(arg); + + // AssetsRoot prefAssetsRoot = new AssetsRoot(Assets.getAssetsRoot().getRelative(PREFERENCES), + // Files.newFile(PropertiesAndDirectories.thisApplicationDir(), PREFERENCES)); + // Assets.downloadZip(prefAssetsRoot, "prefs", null, false, prefsAssetVersion); + + SIMPLTranslationException metaPrefSetException = null; + File metaPrefsFile = new File(localCodeBasePath, ECLIPSE_PREFS_DIR + METAPREFS_XML); + ParsedURL metaPrefsPURL = new ParsedURL(metaPrefsFile); + try + { + metaPrefSet = MetaPrefSet.load(metaPrefsPURL, translationScope); + println("OK: Loaded MetaPrefs from: " + metaPrefsFile); + } + catch (SIMPLTranslationException e) + { + metaPrefSetException = e; + } + + // load the application dir prefs from this machine + // (e.g., c:\Documents and Settings\andruid\Application + // Data\combinFormation\preferences\prefs.xml + // these are the ones that get edited interactively! + + prefSet = PrefSet.load(prefsPURL, translationScope); + if (prefSet != null) + println("Loaded Prefs from: " + prefsPURL); + else + println("No Prefs to load from: " + prefsPURL); + + // now seek the path to an application specific xml preferences file + arg = pop(argStack); + // if (arg == null) + // return; + if (arg != null) + { + // load preferences specific to this invocation + if (arg.endsWith(".xml")) + { + File argPrefsFile = new File(localCodeBasePath, ECLIPSE_PREFS_DIR + arg); + ParsedURL argPrefsPURL = new ParsedURL(argPrefsFile); + try + { + PrefSet argPrefSet = PrefSet.load(argPrefsPURL, translationScope); + if (metaPrefSetException != null) + { + warning("Couldn't load MetaPrefs:"); + metaPrefSetException.printTraceOrMessage(this, "MetaPrefs", metaPrefsPURL); + println("\tContinuing."); + } + if (argPrefSet != null) + { + println("OK: Loaded Prefs from: " + argPrefsFile); + if (prefSet != null) + prefSet.addPrefSet(argPrefSet); + else + prefSet = argPrefSet; + } + else + { + println(""); + String doesntExist = argPrefsFile.exists() ? "" : "\n\tFile does not exist!!!\n\n"; + println("ERROR: Loading Prefs from: " + argPrefsFile + doesntExist); + } + + } + catch (SIMPLTranslationException e) + { + if (metaPrefSetException != null) + { + error("Can't load MetaPrefs or Prefs. Quitting."); + metaPrefSetException.printTraceOrMessage(this, "MetaPrefs", metaPrefsPURL); + e.printStackTrace(); + throw e; + } + // meta prefs o.k. we can continue without having loaded Prefs now + e.printTraceOrMessage(this, "Couldn't load Prefs", argPrefsPURL); + println("\tContinuing."); + } + } + else + argStack.push(arg); + } + else + argStack.push(arg); // let the next code handle returning. + break; + } + System.out.println("Printing Prefs:\n"); + try + { + if (prefSet != null) + SimplTypesScope.serialize(prefSet, System.out, StringFormat.XML); + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + System.out.println("\nPrefs Printed"); + if (prefSet != null) + postProcessPrefs(prefSet); + } + + /** + * Look for pref Ops, if delayed: setup their timers, and also set scope for their ops. + * + * @param prefSet + */ + private void postProcessPrefs(PrefSet prefSet) + { + if (sessionScope == null) + return; + for (Pref pref : prefSet.values()) + if (pref != null) + pref.postLoadHook(sessionScope); + } + + private PrefSet loadPrefsFromJNLP(String prefSpec) + { + PrefSet prefSet = null; + + debugA("loadPrefsFromJNLP()"); + if (prefSpec.startsWith("%3Cpref_set")) + { + try + { + String decodedPrefsXML = URLDecoder.decode(prefSpec, "UTF-8"); + debugA("Loading prefs from JNLP: " + decodedPrefsXML); + + for (ClassDescriptor c : translationScope.getClassDescriptors()) + { + debugA(c.toString()); + } + + prefSet = PrefSet.loadFromCharSequence(decodedPrefsXML, translationScope); + } + catch (UnsupportedEncodingException e) + { + e.printStackTrace(); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + } + return prefSet; + } + + /** + * Get the user.dir property. Form a path from it, ending in slash. See if there is path within + * that that includes the package of baseClass. If so, remove that component from the path. + * + * Form a File from this path, and a ParsedURL from the file. Set codeBase to this ParsedURL. + * + * @param baseClass + * Class of the subclass of this that is the main program that was executed. + * + * @return File that corresponds to the path of the local codeBase. + */ + @Override + protected File deriveLocalFileCodeBase(Class baseClass) + { + // setup codeBase + if (baseClass == null) + baseClass = this.getClass(); + + Package basePackage = baseClass.getPackage(); + String packageName = basePackage.getName(); + String packageNameAsPath = packageName.replace('.', Files.sep); + + String pathName = System.getProperty("user.dir") + Files.sep; + File path = new File(pathName); + String pathString = path.getAbsolutePath(); + + // println("looking for " + packageNameAsPath +" in " + pathString); + + int packageIndex = pathString.lastIndexOf(packageNameAsPath); + if (packageIndex != -1) + { + pathString = pathString.substring(0, packageIndex); + path = new File(pathString + Files.sep); + } + + codeBase = new ParsedURL(path); + println("codeBase=" + codeBase); + return path; + } + + /** + * @see ecologylab.appframework.Environment#runtimeEnv() + */ + @Override + public int runtimeEnv() + { + return APPLICATION; + } + + /** + * @see ecologylab.appframework.Environment#status(String) + */ + @Override + public void showStatus(String s) + { + System.out.println(s); + } + + /** + * @see ecologylab.appframework.Environment#status(String) + */ + @Override + public void status(String msg) + { + if (msg != null) + showStatus(msg); + } + + /** + * @see ecologylab.appframework.Environment#docBase() return the current working directory of the + * application which is "c:\web\code\java\cm" + */ + @Override + public ParsedURL docBase() + { + ParsedURL purl = new ParsedURL(new File(System.getProperty("user.dir"))); + return purl; + } + + @Override + public ParsedURL preferencesDir() + { + ParsedURL codeBase = codeBase(); + ParsedURL purl = codeBase.getRelative(ECLIPSE_PREFS_DIR, "forming preferences dir"); + return purl; + } + + static final String FIREFOX_PATH_WINDOWS = "C:\\Program Files\\Mozilla Firefox\\firefox.exe"; + + static final String FIREFOX_PATH_WINDOWS_64 = "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe"; + + static final String FIREFOX_PATH_VIRT = "C:\\Program Files (x86)\\Microsoft Application Virtualization Client\\sfttray.exe"; + + // TODO -- use "open" on the mac!!! + static final String FIREFOX_PATH_MAC = "/Applications/Firefox.app/Contents/MacOS/firefox"; + + // static final String FIREFOX_PATH_MAC = null; + static final String SAFARI_PATH_MAC = "/Applications/Safari.app/Contents/MacOS/Safari"; + + static final String FIREFOX_PATH_LINUX = "/usr/bin/firefox"; + + static final String IE_PATH_WINDOWS = "C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE"; + + static String browserPath; + + /** + * Get the operating system dependent path to a suitable web browser for navigating to a web page. + * This is also dependent on what web browser(s) the user has installed. In particular, we use + * Firefox if it is in its normal place! + * + * @return String that specifies the OS and browser-specific command. + */ + static String getBrowserPath() + { + int os = PropertiesAndDirectories.os(); + String result = browserPath; + if (result == null) + { + switch (os) + { + case PropertiesAndDirectories.XP: + case PropertiesAndDirectories.VISTA_AND_7: + if (!Pref.lookupBoolean("navigate_with_ie")) + result = FIREFOX_PATH_WINDOWS; + if (result != null) + { + File existentialTester = new File(result); + if (!existentialTester.exists()) + { + result = FIREFOX_PATH_WINDOWS_64; + existentialTester = new File(result); + if (!existentialTester.exists()) + { + result = IE_PATH_WINDOWS; + existentialTester = new File(result); + if (!existentialTester.exists()) + result = null; + } + } + } + break; + case PropertiesAndDirectories.MAC: + result = "/usr/bin/open"; + break; + default: + error(PropertiesAndDirectories.getOsName(), "go(ParsedURL) not supported"); + break; + } + if (result != null) + { + browserPath = result; + } + } + return result; + } + + static String[] cachedNavigateArgs; + + /** + * Get the operating system dependent path to a suitable web browser for navigating to a web page. + * This is also dependent on what web browser(s) the user has installed. In particular, we use + * Firefox if it is in its normal place! + * + * @return String that specifies the OS and browser-specific command. + */ + static String[] getNavigateArgs() + { + int os = PropertiesAndDirectories.os(); + String[] result = cachedNavigateArgs; + if (result == null) + { + switch (os) + { + case PropertiesAndDirectories.XP: + case PropertiesAndDirectories.VISTA_AND_7: + String path = null; + if (!Pref.lookupBoolean("navigate_with_ie")) + path = FIREFOX_PATH_WINDOWS; + if (path != null) + { + File existentialTester = new File(path); + firefoxExists = existentialTester.exists(); + if (!firefoxExists) + { + path = FIREFOX_PATH_WINDOWS_64; + existentialTester = new File(path); + firefoxExists = existentialTester.exists(); + } + if (firefoxExists) + { // cool! firefox + result = new String[3]; + result[0] = path; + result[1] = "-new-tab"; + } else { + //Use the SCC Virtualization Path + path = FIREFOX_PATH_VIRT; + existentialTester = new File(path); + firefoxExists = existentialTester.exists(); + if(firefoxExists) + { + result = new String[5]; + result[0] = path; + result[1] = "/launch"; + result[2] = "\"Mozilla Firefox 11\""; + result[3] = "-new-tab"; + } + } + + } + if (result == null) + { + path = IE_PATH_WINDOWS; + File existentialTester = new File(path); + if (existentialTester.exists()) + { + result = new String[2]; + result[0] = path; + } + } + break; + case PropertiesAndDirectories.MAC: + result = new String[4]; + result[0] = "/usr/bin/open"; + result[1] = "-a"; + result[2] = "firefox"; + firefoxExists = true; + break; + case PropertiesAndDirectories.LINUX: + result = new String[2]; + result[0] = FIREFOX_PATH_LINUX; + firefoxExists = true; + break; + default: + error(PropertiesAndDirectories.getOsName(), "go(ParsedURL) not supported"); + break; + } + if (result != null) + { + cachedNavigateArgs = result; + } + } + return result; + } + + + /** + * Returns true if firefox was found on this system. + * @return + */ + @Override + public boolean hasFirefox() + { + getNavigateArgs();//sets firefoxExists if true + return firefoxExists; + } + + + /** + * Navigate to the purl using the best browser we can find. + * + * @param purl + * @param frame + */ + @Override + public void navigate(ParsedURL purl, String frame) + { + String[] navigateArgs = getNavigateArgs(); + if (navigateArgs != null && purl != null) + { + String purlString = purl.toString(); + int numArgs = navigateArgs.length; + navigateArgs[numArgs - 1] = purlString; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < numArgs; i++) + sb.append(navigateArgs[i]).append(' '); + Debug.println("navigate: " + sb); + try + { + Process p = Runtime.getRuntime().exec(navigateArgs); + } + catch (IOException e) + { + error("navigate() - caught exception: "); + e.printStackTrace(); + } + } + else + error("navigate() - Can't find browser to navigate to."); + } + + @Override + public int browser() + { + return APPLICATION; + } + + /** + * Called at the end of an invocation. Calls System.exit(code). + * + * @param code + * -- 0 for normal. other values are application specific. + */ + @Override + public void exit(int code) + { + System.exit(code); + } + + public static boolean isInUse() + { + return inUse; + } + + public static boolean runningInEclipse() + { + return LaunchType.ECLIPSE == LAUNCH_TYPE_PREF.value(); + } + + public static boolean runningLocalhost() + { + return LaunchType.LOCAL_JNLP == LAUNCH_TYPE_PREF.value(); + } + + /** + * Create and show an editor for preferences, iff the MetaPrefSet and PrefSet are non-null. If the + * PrefSet is null, a new empty one will be created for the editor to use. + * + * @return + */ + public Object createPrefsEditor(final boolean createJFrame, final boolean isStandalone) + { + Object result = null; + if (metaPrefSet != null) + { + if (prefSet == null) + prefSet = new PrefSet(); + result = FundamentalPlatformSpecifics.get().getOrCreatePrefsEditor(metaPrefSet, prefSet, prefsPURL, createJFrame, isStandalone); + } + return result; + } + + /** + * Create and show an editor for preferences, iff the MetaPrefSet and PrefSet are non-null. If the + * PrefSet is null, a new empty one will be created for the editor to use. + * + * @return + */ + public Object createPrefsEditor() + { + return this.createPrefsEditor(true, false); + } + + /** + * + * @return MetaPrefSet for this application, loaded from standard locations. + */ + protected MetaPrefSet metaPrefSet() + { + return metaPrefSet; + } + + @Override + public String getApplicationName() + { + return PropertiesAndDirectories.applicationName; + } +} diff --git a/simplCore/src/ecologylab/appframework/StatusReporter.java b/simplCore/src/ecologylab/appframework/StatusReporter.java index ff900c2d..3c88f58e 100644 --- a/simplCore/src/ecologylab/appframework/StatusReporter.java +++ b/simplCore/src/ecologylab/appframework/StatusReporter.java @@ -1,35 +1,35 @@ -package ecologylab.appframework; - -/** - * Interface for objects that report status to the user. - * - * @author andruid - * - */ -public interface StatusReporter -{ - /** - * Submit a message for display in the status line. - * If there's nothing showing now, it will be displayed immediately. - * Otherwise, it will be queued. - * Uses the default minimum longevity level of 1 * 1/4 second. - */ - public void display(String msg); - - /** - * Submit a message for display in the status line. - * If there's nothing showing now, it will be displayed immediately. - * Otherwise, it will be queued. - * - * @param msg String to display. - * @param priority Measure minimum message longevity of message in units - * of 1/4 second. - */ - public void display(String msg, int priority); - - - public void display(String msg, int longevity, - int progessNumerator, int progessDenominator); - - -} +package ecologylab.appframework; + +/** + * Interface for objects that report status to the user. + * + * @author andruid + * + */ +public interface StatusReporter +{ + /** + * Submit a message for display in the status line. + * If there's nothing showing now, it will be displayed immediately. + * Otherwise, it will be queued. + * Uses the default minimum longevity level of 1 * 1/4 second. + */ + public void display(String msg); + + /** + * Submit a message for display in the status line. + * If there's nothing showing now, it will be displayed immediately. + * Otherwise, it will be queued. + * + * @param msg String to display. + * @param priority Measure minimum message longevity of message in units + * of 1/4 second. + */ + public void display(String msg, int priority); + + + public void display(String msg, int longevity, + int progessNumerator, int progessDenominator); + + +} diff --git a/simplCore/src/ecologylab/appframework/TraceSlots.java b/simplCore/src/ecologylab/appframework/TraceSlots.java index ff8f1d67..ec3aa464 100644 --- a/simplCore/src/ecologylab/appframework/TraceSlots.java +++ b/simplCore/src/ecologylab/appframework/TraceSlots.java @@ -1,29 +1,29 @@ -/** - * - */ -package ecologylab.appframework; - -import ecologylab.generic.Debug; - -/** - * Peephole slots used for tracing concurrent real time deadlocks. - * - * @author andruid - * - */ -public class TraceSlots extends Debug -{ - public boolean fatPixelGridRendering; - public int rolloverRenderStatus; - public int dragDropEndStatus; - public int setFocusStatus; - public int mouseExitStatus; - static public int rolloverRaiseStatus; - public int handleMouseEventStatus; - public int internalFocusStatus; - public static int renderStatus; - public int handleMouseEventId; - static public int pieMenuRaiseStatus; - static public int pieMenuRenderStatus; - -} +/** + * + */ +package ecologylab.appframework; + +import ecologylab.generic.Debug; + +/** + * Peephole slots used for tracing concurrent real time deadlocks. + * + * @author andruid + * + */ +public class TraceSlots extends Debug +{ + public boolean fatPixelGridRendering; + public int rolloverRenderStatus; + public int dragDropEndStatus; + public int setFocusStatus; + public int mouseExitStatus; + static public int rolloverRaiseStatus; + public int handleMouseEventStatus; + public int internalFocusStatus; + public static int renderStatus; + public int handleMouseEventId; + static public int pieMenuRaiseStatus; + static public int pieMenuRenderStatus; + +} diff --git a/simplCore/src/ecologylab/appframework/UndoRedo.java b/simplCore/src/ecologylab/appframework/UndoRedo.java index ab94ca36..0e22bab7 100644 --- a/simplCore/src/ecologylab/appframework/UndoRedo.java +++ b/simplCore/src/ecologylab/appframework/UndoRedo.java @@ -1,183 +1,183 @@ -package ecologylab.appframework; - -import ecologylab.appframework.types.prefs.Pref; -import ecologylab.appframework.types.prefs.PrefInt; -import ecologylab.collections.SyncLinkedList; -import ecologylab.generic.Debug; -import ecologylab.oodss.logging.MixedInitiativeOp; - -/** - * Undo and Redo Mixed Initiative Operations. - * @author andruid, alexgrau - */ -public class UndoRedo extends Debug{ - - /** - * Synced Linked List of Undo Operations. - */ - protected final SyncLinkedList undoStack = new SyncLinkedList(); - - /** - * Syned Linked List of Redo Operations - */ - protected final SyncLinkedList redoStack = new SyncLinkedList(); - - /** - * Semaphor Object Used For Undo and Redo - */ - protected final Object undoRedoSemaphore = new Object(); - - /** - * Sets the Int Prefs for the number of Undo/Redo Levels - */ - protected final PrefInt undoLevels = Pref.usePrefInt(UNDO_LEVELS, DEFAULT_UNDO_LEVELS); - - /** - * Number of possible Undo/Redo levels - */ - protected static final int DEFAULT_UNDO_LEVELS = 32; - - public static final String UNDO_LEVELS = "undo_levels"; - - protected int humanUndoCount; - protected int humanRedoCount; - - /** - * Construct an Undo/Redo Object - */ - public UndoRedo(){ - super(); - } - - /** - * Undo an Operation. Returns the Operations. - * @return - */ - public MixedInitiativeOp undo(){ - synchronized (undoRedoSemaphore){ - MixedInitiativeOp op = popUndo(); - if(op == null) - return null; - op.performAction(true); - pushRedo(op); - return op; - } - } - - /** - * Redo an Operation. Returns the Operation. - * @return - */ - public MixedInitiativeOp redo(){ - synchronized (undoRedoSemaphore){ - MixedInitiativeOp op = popRedo(); - if (op == null) - return null; - op.performAction(false); - pushUndo(op); - return op; - } - } - - /** - * Pushes an Operation onto the undo stack. - * Clears the redo stack because a new operation has taken place. - * @param op - */ - public MixedInitiativeOp pushOpToUndo(MixedInitiativeOp op){ - pushUndo(op); - clearRedo(); - return op; - } - - /** - * Pushes an Operation onto the Undo stack. - * If too many operations, removes oldest and adds op. - * @param op - */ - public void pushUndo(MixedInitiativeOp op){ - synchronized (undoStack){ - while (undoStack.size() >= undoLevels.value()){ - MixedInitiativeOp oldOp = (MixedInitiativeOp) undoStack.removeFirst(); - if (oldOp.isHuman()) - humanUndoCount--; - oldOp.recycle(false); - } - undoStack.addLast(op); - humanUndoCount++; - } - } - - /** - * Pops an Operation from the Undo stack. - * If empty, returns null. - * @return - */ - public MixedInitiativeOp popUndo(){ - synchronized (undoStack){ - return undoStack.isEmpty() ? null : (MixedInitiativeOp) undoStack.removeLast(); - } - } - - /** - * Peak an Operation from the Undo stack. - * If empty, returns null. - * @return - */ - public MixedInitiativeOp peekUndo(){ - synchronized (undoStack){ - return undoStack.isEmpty() ? null : (MixedInitiativeOp) undoStack.getLast(); - } - } - - /** - * Pushes an Operation onto the Redo stack. - * @param op - */ - private void pushRedo(MixedInitiativeOp op){ - synchronized (redoStack){ - redoStack.addLast(op); - } - } - - /** - * Pops an Operation from the Redo stack. - * If empty, then returns null. - * @return - */ - private MixedInitiativeOp popRedo(){ - synchronized (redoStack){ - return redoStack.isEmpty() ? null : (MixedInitiativeOp) redoStack.removeLast(); - } - } - - /** - * Clears both the undo and redo stacks. - */ - public synchronized void clear(){ - synchronized (undoStack){ - while (!undoStack.isEmpty()){ - MixedInitiativeOp op = popUndo(); - op.recycle(true); - } - } - synchronized (redoStack){ - while (!redoStack.isEmpty()){ - MixedInitiativeOp op = popRedo(); - op.recycle(true); - } - } - } - - /** - * Clears and recycles the redo stack after a new operation has been done. - */ - protected void clearRedo(){ - synchronized (redoStack){ - while (!redoStack.isEmpty()){ - MixedInitiativeOp op = popRedo(); - op.recycle(true); - } - } - } -} +package ecologylab.appframework; + +import ecologylab.appframework.types.prefs.Pref; +import ecologylab.appframework.types.prefs.PrefInt; +import ecologylab.collections.SyncLinkedList; +import ecologylab.generic.Debug; +import ecologylab.oodss.logging.MixedInitiativeOp; + +/** + * Undo and Redo Mixed Initiative Operations. + * @author andruid, alexgrau + */ +public class UndoRedo extends Debug{ + + /** + * Synced Linked List of Undo Operations. + */ + protected final SyncLinkedList undoStack = new SyncLinkedList(); + + /** + * Syned Linked List of Redo Operations + */ + protected final SyncLinkedList redoStack = new SyncLinkedList(); + + /** + * Semaphor Object Used For Undo and Redo + */ + protected final Object undoRedoSemaphore = new Object(); + + /** + * Sets the Int Prefs for the number of Undo/Redo Levels + */ + protected final PrefInt undoLevels = Pref.usePrefInt(UNDO_LEVELS, DEFAULT_UNDO_LEVELS); + + /** + * Number of possible Undo/Redo levels + */ + protected static final int DEFAULT_UNDO_LEVELS = 32; + + public static final String UNDO_LEVELS = "undo_levels"; + + protected int humanUndoCount; + protected int humanRedoCount; + + /** + * Construct an Undo/Redo Object + */ + public UndoRedo(){ + super(); + } + + /** + * Undo an Operation. Returns the Operations. + * @return + */ + public MixedInitiativeOp undo(){ + synchronized (undoRedoSemaphore){ + MixedInitiativeOp op = popUndo(); + if(op == null) + return null; + op.performAction(true); + pushRedo(op); + return op; + } + } + + /** + * Redo an Operation. Returns the Operation. + * @return + */ + public MixedInitiativeOp redo(){ + synchronized (undoRedoSemaphore){ + MixedInitiativeOp op = popRedo(); + if (op == null) + return null; + op.performAction(false); + pushUndo(op); + return op; + } + } + + /** + * Pushes an Operation onto the undo stack. + * Clears the redo stack because a new operation has taken place. + * @param op + */ + public MixedInitiativeOp pushOpToUndo(MixedInitiativeOp op){ + pushUndo(op); + clearRedo(); + return op; + } + + /** + * Pushes an Operation onto the Undo stack. + * If too many operations, removes oldest and adds op. + * @param op + */ + public void pushUndo(MixedInitiativeOp op){ + synchronized (undoStack){ + while (undoStack.size() >= undoLevels.value()){ + MixedInitiativeOp oldOp = (MixedInitiativeOp) undoStack.removeFirst(); + if (oldOp.isHuman()) + humanUndoCount--; + oldOp.recycle(false); + } + undoStack.addLast(op); + humanUndoCount++; + } + } + + /** + * Pops an Operation from the Undo stack. + * If empty, returns null. + * @return + */ + public MixedInitiativeOp popUndo(){ + synchronized (undoStack){ + return undoStack.isEmpty() ? null : (MixedInitiativeOp) undoStack.removeLast(); + } + } + + /** + * Peak an Operation from the Undo stack. + * If empty, returns null. + * @return + */ + public MixedInitiativeOp peekUndo(){ + synchronized (undoStack){ + return undoStack.isEmpty() ? null : (MixedInitiativeOp) undoStack.getLast(); + } + } + + /** + * Pushes an Operation onto the Redo stack. + * @param op + */ + private void pushRedo(MixedInitiativeOp op){ + synchronized (redoStack){ + redoStack.addLast(op); + } + } + + /** + * Pops an Operation from the Redo stack. + * If empty, then returns null. + * @return + */ + private MixedInitiativeOp popRedo(){ + synchronized (redoStack){ + return redoStack.isEmpty() ? null : (MixedInitiativeOp) redoStack.removeLast(); + } + } + + /** + * Clears both the undo and redo stacks. + */ + public synchronized void clear(){ + synchronized (undoStack){ + while (!undoStack.isEmpty()){ + MixedInitiativeOp op = popUndo(); + op.recycle(true); + } + } + synchronized (redoStack){ + while (!redoStack.isEmpty()){ + MixedInitiativeOp op = popRedo(); + op.recycle(true); + } + } + } + + /** + * Clears and recycles the redo stack after a new operation has been done. + */ + protected void clearRedo(){ + synchronized (redoStack){ + while (!redoStack.isEmpty()){ + MixedInitiativeOp op = popRedo(); + op.recycle(true); + } + } + } +} diff --git a/simplCore/src/ecologylab/appframework/macos/MacOSApp.java b/simplCore/src/ecologylab/appframework/macos/MacOSApp.java index a04ea4db..827ee42f 100644 --- a/simplCore/src/ecologylab/appframework/macos/MacOSApp.java +++ b/simplCore/src/ecologylab/appframework/macos/MacOSApp.java @@ -1,23 +1,23 @@ -package ecologylab.appframework.macos; - -import ecologylab.appframework.MacOSAppHandler; - -/** - * Shadowed no-op version so we can avoid compile errors on non-mac platforms. - * - * Make sure if you're on the mac that the ecologylabMacOS project is before ecologylabFundamental. - * - * @author andrew - * - */ -public class MacOSApp -{ - /** - * Shadowed no-op version so we can avoid compile errors on non-mac platforms. - * - * @param macOSAppHandler - */ - public static void addListener(MacOSAppHandler macOSAppHandler) - { - } -} +package ecologylab.appframework.macos; + +import ecologylab.appframework.MacOSAppHandler; + +/** + * Shadowed no-op version so we can avoid compile errors on non-mac platforms. + * + * Make sure if you're on the mac that the ecologylabMacOS project is before ecologylabFundamental. + * + * @author andrew + * + */ +public class MacOSApp +{ + /** + * Shadowed no-op version so we can avoid compile errors on non-mac platforms. + * + * @param macOSAppHandler + */ + public static void addListener(MacOSAppHandler macOSAppHandler) + { + } +} diff --git a/simplCore/src/ecologylab/appframework/package.html b/simplCore/src/ecologylab/appframework/package.html index c7c3054c..f9a7d672 100644 --- a/simplCore/src/ecologylab/appframework/package.html +++ b/simplCore/src/ecologylab/appframework/package.html @@ -1,4 +1,4 @@ - -Interface Ecology Lab Application Development Framework makes -interfacing with the runtime platform easier. - + +Interface Ecology Lab Application Development Framework makes +interfacing with the runtime platform easier. + diff --git a/simplCore/src/ecologylab/appframework/types/AppFrameworkTranslations.java b/simplCore/src/ecologylab/appframework/types/AppFrameworkTranslations.java index e3000aea..2f0fdc6f 100644 --- a/simplCore/src/ecologylab/appframework/types/AppFrameworkTranslations.java +++ b/simplCore/src/ecologylab/appframework/types/AppFrameworkTranslations.java @@ -1,40 +1,40 @@ -package ecologylab.appframework.types; - -import ecologylab.appframework.types.prefs.PrefsTranslationsProvider; -import ecologylab.generic.Debug; -import ecologylab.oodss.messages.DefaultServicesTranslations; -import ecologylab.serialization.SimplTypesScope; - -/** - * Base translations for applications that use the ecologylab appframework and services. - * - * @author andruid - * @author andrew - */ -public class AppFrameworkTranslations extends Debug -{ - public static final String PACKAGE_NAME = "ecologylab.appframework.types"; - - public static final SimplTypesScope inheritedTranslations[] = - { - DefaultServicesTranslations.get(), - PrefsTranslationsProvider.get() - }; - - - - /** - * Do not use this accessor. - */ - private AppFrameworkTranslations() - { - } - /** - * This accessor will work from anywhere, in any order, and stay efficient. - * @return - */ - public static SimplTypesScope get() - { - return SimplTypesScope.get(PACKAGE_NAME, inheritedTranslations); - } -} +package ecologylab.appframework.types; + +import ecologylab.appframework.types.prefs.PrefsTranslationsProvider; +import ecologylab.generic.Debug; +import ecologylab.oodss.messages.DefaultServicesTranslations; +import ecologylab.serialization.SimplTypesScope; + +/** + * Base translations for applications that use the ecologylab appframework and services. + * + * @author andruid + * @author andrew + */ +public class AppFrameworkTranslations extends Debug +{ + public static final String PACKAGE_NAME = "ecologylab.appframework.types"; + + public static final SimplTypesScope inheritedTranslations[] = + { + DefaultServicesTranslations.get(), + PrefsTranslationsProvider.get() + }; + + + + /** + * Do not use this accessor. + */ + private AppFrameworkTranslations() + { + } + /** + * This accessor will work from anywhere, in any order, and stay efficient. + * @return + */ + public static SimplTypesScope get() + { + return SimplTypesScope.get(PACKAGE_NAME, inheritedTranslations); + } +} diff --git a/simplCore/src/ecologylab/appframework/types/AssetState.java b/simplCore/src/ecologylab/appframework/types/AssetState.java index 26fcb93c..da87b03f 100644 --- a/simplCore/src/ecologylab/appframework/types/AssetState.java +++ b/simplCore/src/ecologylab/appframework/types/AssetState.java @@ -1,56 +1,56 @@ -/** - * - */ -package ecologylab.appframework.types; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.element.IMappable; - -/** - * @author robinson - * - */ -public class AssetState extends ElementState implements IMappable -{ - @simpl_scalar String name; - @simpl_scalar float version; - - public AssetState() - { - - } - public AssetState(String name) - { - this.name = name; - } - /** - * @return Returns the version. - */ - public float getVersion() - { - return version; - } - - /** - * @param version The version to set. - */ - public void setVersion(float version) - { - this.version = version; - } - - /** - * @return Returns the id. - */ - public String getName() - { - return name; - } - - @Override - public String key() - { - return name; - } -} +/** + * + */ +package ecologylab.appframework.types; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.element.IMappable; + +/** + * @author robinson + * + */ +public class AssetState extends ElementState implements IMappable +{ + @simpl_scalar String name; + @simpl_scalar float version; + + public AssetState() + { + + } + public AssetState(String name) + { + this.name = name; + } + /** + * @return Returns the version. + */ + public float getVersion() + { + return version; + } + + /** + * @param version The version to set. + */ + public void setVersion(float version) + { + this.version = version; + } + + /** + * @return Returns the id. + */ + public String getName() + { + return name; + } + + @Override + public String key() + { + return name; + } +} diff --git a/simplCore/src/ecologylab/appframework/types/AssetsState.java b/simplCore/src/ecologylab/appframework/types/AssetsState.java index 71aeedcd..cef3e96c 100644 --- a/simplCore/src/ecologylab/appframework/types/AssetsState.java +++ b/simplCore/src/ecologylab/appframework/types/AssetsState.java @@ -1,60 +1,60 @@ -package ecologylab.appframework.types; - -import java.util.Collection; -import java.util.HashMap; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_map; -import ecologylab.serialization.annotations.simpl_nowrap; - -/** - * Handles the loading and parsing of the asset version XML file - * - * @author robinson - * @author andruid - */ -@simpl_inherit public class AssetsState extends ElementState -{ - @simpl_map("asset") - @simpl_nowrap - HashMap assetsMap = new HashMap(); - - public Collection getAssetStates() - { - return assetsMap.values(); - } - - /** - * @param asset - */ - private void register(AssetState asset) - { - assetsMap.put(asset.getName(), asset); - } - - public AssetState lookup(String name) - { - return assetsMap.get(name); - } - - public AssetState lookupAndUpdate(String name) - { - AssetState asset = lookup(name); - if (asset == null) - { - asset = update(name); - } - return asset; - } - - /** - * @return - */ - public AssetState update(String name) - { - AssetState asset = new AssetState(name); - register(asset); - return asset; - } +package ecologylab.appframework.types; + +import java.util.Collection; +import java.util.HashMap; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_map; +import ecologylab.serialization.annotations.simpl_nowrap; + +/** + * Handles the loading and parsing of the asset version XML file + * + * @author robinson + * @author andruid + */ +@simpl_inherit public class AssetsState extends ElementState +{ + @simpl_map("asset") + @simpl_nowrap + HashMap assetsMap = new HashMap(); + + public Collection getAssetStates() + { + return assetsMap.values(); + } + + /** + * @param asset + */ + private void register(AssetState asset) + { + assetsMap.put(asset.getName(), asset); + } + + public AssetState lookup(String name) + { + return assetsMap.get(name); + } + + public AssetState lookupAndUpdate(String name) + { + AssetState asset = lookup(name); + if (asset == null) + { + asset = update(name); + } + return asset; + } + + /** + * @return + */ + public AssetState update(String name) + { + AssetState asset = new AssetState(name); + register(asset); + return asset; + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/appframework/types/AssetsTranslations.java b/simplCore/src/ecologylab/appframework/types/AssetsTranslations.java index 013ec9a3..9faa0349 100644 --- a/simplCore/src/ecologylab/appframework/types/AssetsTranslations.java +++ b/simplCore/src/ecologylab/appframework/types/AssetsTranslations.java @@ -1,35 +1,35 @@ -/** - * - */ -package ecologylab.appframework.types; - -import ecologylab.generic.Debug; -import ecologylab.serialization.SimplTypesScope; - -/** - * Simple translations used just for loading the assets.xml file. - * - * @author robinson - * @author andruid - */ -public class AssetsTranslations extends Debug -{ - public static final String PACKAGE_NAME = "ecologylab.assets.types"; - - public static final Class TRANSLATIONS[] = - { - AssetsState.class, - AssetState.class, - - }; - - /** - * Get existing TranslationSpace with this name, or create a new one, and map it. - * - * @return TranslationSpace with simple translations used just for loading the assets.xml file. - */ - public static SimplTypesScope get() - { - return SimplTypesScope.get(PACKAGE_NAME, TRANSLATIONS); - } -} +/** + * + */ +package ecologylab.appframework.types; + +import ecologylab.generic.Debug; +import ecologylab.serialization.SimplTypesScope; + +/** + * Simple translations used just for loading the assets.xml file. + * + * @author robinson + * @author andruid + */ +public class AssetsTranslations extends Debug +{ + public static final String PACKAGE_NAME = "ecologylab.assets.types"; + + public static final Class TRANSLATIONS[] = + { + AssetsState.class, + AssetState.class, + + }; + + /** + * Get existing TranslationSpace with this name, or create a new one, and map it. + * + * @return TranslationSpace with simple translations used just for loading the assets.xml file. + */ + public static SimplTypesScope get() + { + return SimplTypesScope.get(PACKAGE_NAME, TRANSLATIONS); + } +} diff --git a/simplCore/src/ecologylab/appframework/types/package.html b/simplCore/src/ecologylab/appframework/types/package.html index b5bc4b46..ae40a564 100644 --- a/simplCore/src/ecologylab/appframework/types/package.html +++ b/simplCore/src/ecologylab/appframework/types/package.html @@ -1,4 +1,4 @@ - -Type declarations for the Interface Ecology Lab Application -Development Framework. - + +Type declarations for the Interface Ecology Lab Application +Development Framework. + diff --git a/simplCore/src/ecologylab/appframework/types/prefs/Choice.java b/simplCore/src/ecologylab/appframework/types/prefs/Choice.java index 6d43d952..441c3375 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/Choice.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/Choice.java @@ -1,58 +1,58 @@ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Multi-choice option for a preference. - * This should be used for options that have - * non-standard text associated with them. - * (Standard text would be "Yes"/"No" for Booleans.) - */ -abstract public class Choice extends ElementState -{ - /** - * The name for a choice - */ - @simpl_scalar String name; - /** - * The label text for a choice - */ - @simpl_scalar String label; - //@xml_attribute T value; - - public Choice() - { - super(); - } - - /** - * Get the value of a choice. Type-specific. - */ - public abstract T getValue(); - - /** - * Set the value of a choice. Type-specific. - */ - public abstract void setValue(T newValue); - - /** - * Get the name of a choice - * - * @return Name of a choice - */ - public String getName() - { - return this.name; - } - - /** - * Get the label of a choice - * - * @return Label of a choice - */ - public String getLabel() - { - return this.label; - } -} +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Multi-choice option for a preference. + * This should be used for options that have + * non-standard text associated with them. + * (Standard text would be "Yes"/"No" for Booleans.) + */ +abstract public class Choice extends ElementState +{ + /** + * The name for a choice + */ + @simpl_scalar String name; + /** + * The label text for a choice + */ + @simpl_scalar String label; + //@xml_attribute T value; + + public Choice() + { + super(); + } + + /** + * Get the value of a choice. Type-specific. + */ + public abstract T getValue(); + + /** + * Set the value of a choice. Type-specific. + */ + public abstract void setValue(T newValue); + + /** + * Get the name of a choice + * + * @return Name of a choice + */ + public String getName() + { + return this.name; + } + + /** + * Get the label of a choice + * + * @return Label of a choice + */ + public String getLabel() + { + return this.label; + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/ChoiceBoolean.java b/simplCore/src/ecologylab/appframework/types/prefs/ChoiceBoolean.java index 35e83906..2fb4dbd7 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/ChoiceBoolean.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/ChoiceBoolean.java @@ -1,53 +1,53 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - - -/** - * A Boolean Choice object, for a multi-choice preference. - * @author awebb - * - */ -@simpl_inherit -public class ChoiceBoolean extends Choice -{ - /** - * Value of the choice - */ - @simpl_scalar boolean value; - - - /** - * - */ - public ChoiceBoolean() - { - super(); - } - - /** - * Get the value of a choice - * - * @return value Value of the choice - */ - @Override - public Boolean getValue() - { - return value; - } - - /** - * Set the value of a choice. - * - * @param newValue New value the choice will be set to. - */ - @Override public void setValue(Boolean newValue) - { - this.value = newValue; - } - -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + + +/** + * A Boolean Choice object, for a multi-choice preference. + * @author awebb + * + */ +@simpl_inherit +public class ChoiceBoolean extends Choice +{ + /** + * Value of the choice + */ + @simpl_scalar boolean value; + + + /** + * + */ + public ChoiceBoolean() + { + super(); + } + + /** + * Get the value of a choice + * + * @return value Value of the choice + */ + @Override + public Boolean getValue() + { + return value; + } + + /** + * Set the value of a choice. + * + * @param newValue New value the choice will be set to. + */ + @Override public void setValue(Boolean newValue) + { + this.value = newValue; + } + +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/ChoiceFloat.java b/simplCore/src/ecologylab/appframework/types/prefs/ChoiceFloat.java index c6c4467b..12480b82 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/ChoiceFloat.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/ChoiceFloat.java @@ -1,43 +1,43 @@ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * A Float Choice object, for a multi-choice preference. - * @author awebb - * - */ -@simpl_inherit -public class ChoiceFloat extends Choice -{ - /** - * Value of the choice - */ - @simpl_scalar float value; - - public ChoiceFloat() - { - super(); - } - - /** - * Get the value of a choice - * - * @return value Value of the choice - */ - @Override public void setValue(Float newValue) - { - this.value = newValue; - } - - /** - * Set the value of a choice. - * - * @param newValue New value the choice will be set to. - */ - @Override public Float getValue() - { - return this.value; - } -} +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * A Float Choice object, for a multi-choice preference. + * @author awebb + * + */ +@simpl_inherit +public class ChoiceFloat extends Choice +{ + /** + * Value of the choice + */ + @simpl_scalar float value; + + public ChoiceFloat() + { + super(); + } + + /** + * Get the value of a choice + * + * @return value Value of the choice + */ + @Override public void setValue(Float newValue) + { + this.value = newValue; + } + + /** + * Set the value of a choice. + * + * @param newValue New value the choice will be set to. + */ + @Override public Float getValue() + { + return this.value; + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/ChoiceInt.java b/simplCore/src/ecologylab/appframework/types/prefs/ChoiceInt.java index 2d19339a..c60714db 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/ChoiceInt.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/ChoiceInt.java @@ -1,43 +1,43 @@ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * An Integer Choice object, for a multi-choice preference. - * @author awebb - * - */ -@simpl_inherit -public class ChoiceInt extends Choice -{ - /** - * Value of the choice - */ - @simpl_scalar int value; - - public ChoiceInt() - { - super(); - } - - /** - * Get the value of a choice - * - * @return value Value of the choice - */ - @Override public void setValue(Integer newValue) - { - this.value = newValue; - } - - /** - * Set the value of a choice. - * - * @param newValue New value the choice will be set to. - */ - @Override public Integer getValue() - { - return this.value; - } -} +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * An Integer Choice object, for a multi-choice preference. + * @author awebb + * + */ +@simpl_inherit +public class ChoiceInt extends Choice +{ + /** + * Value of the choice + */ + @simpl_scalar int value; + + public ChoiceInt() + { + super(); + } + + /** + * Get the value of a choice + * + * @return value Value of the choice + */ + @Override public void setValue(Integer newValue) + { + this.value = newValue; + } + + /** + * Set the value of a choice. + * + * @param newValue New value the choice will be set to. + */ + @Override public Integer getValue() + { + return this.value; + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/MetaPref.java b/simplCore/src/ecologylab/appframework/types/prefs/MetaPref.java index ef116310..e9451b57 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/MetaPref.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/MetaPref.java @@ -1,516 +1,516 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import java.util.ArrayList; -import java.util.LinkedHashMap; - -import ecologylab.collections.Scope; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_classes; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.types.ScalarType; - -/** - * Metadata about a Preference. Defines information to enable editing the Preference. - * - * @author andruid - * - */ - -@simpl_inherit -public abstract class MetaPref extends ElementState implements WidgetTypes -{ - /** The global registry of Pref objects. Used for providing lookup services. */ - static final Scope allMetaPrefsMap = new Scope(); - - /** - * Unique identifier for Preference name with convenient lookup in automatically generated - * HashMap. - */ - @simpl_tag("id") - @simpl_scalar - String m_id; - - /** - * This is the short text that appears in the Swing panel for editing the value. - */ - @simpl_scalar - String description; - - /** - * This is longer text about that describes what the Preference does and more about the - * implications of its value. - */ - @simpl_scalar - String helpText; - - /** - * Type of graphical user interface component used to interact with it. Must be a constant defined - * in the interface WidgetTypes If this value is left as null, it should default to TEXT_FIELD. - */ - @simpl_scalar - String widget; - - /** - * Categories enable tabbed panes of preferences to be edited. - */ - @simpl_scalar - String category; - - /** - * Whether or not the application has to restart for this pref change to take effect. - */ - @simpl_scalar - boolean requiresRestart; - - /** - * optional; for preferences with three or more choices - */ - @simpl_collection - @simpl_classes( - { ChoiceBoolean.class, ChoiceFloat.class, ChoiceInt.class }) - ArrayList> choices; - - ScalarType scalarType; - - /** - * LinkedHashMap to make locating exact choices easier - */ - private LinkedHashMap> choiceList; - - ValueChangedListener valueChangedListener; - - // @xml_attribute T defaultValue; - - // @xml_nested RangeState range; - /** - * Instantiate. - * - * @param scalarType - * TODO - */ - public MetaPref(ScalarType scalarType) - { - super(); - this.scalarType = scalarType; - } - - /** - * Gets the default value of a MetaPref; type-specific behavior. - * - * @return Default value of MetaPref - */ - public abstract T getDefaultValue(); - - /** - * Gets the min value of the range of a MetaPref. - * - * @return Min value of a MetaPref - */ - public abstract T getMinValue(); - - /** - * Gets the max value of the range of a MetaPref. - * - * @return Max value of a MetaPref - */ - public abstract T getMaxValue(); - - /** - * Gets the category for a MetaPref. - * - * @return Category of MetaPref - */ - public String getCategory() - { - return category; - } - - /** - * Gets the description for a MetaPref. - * - * @return Description of MetaPref - */ - public String getDescription() - { - String result = description; - if (requiresRestart) - result += "
Requires restart to take effect."; - return result; - } - - /** - * Gets the help text for a MetaPref. - * - * @return Help Text of MetaPref - */ - public String getHelpText() - { - return helpText; - } - - /** - * Gets the ID of a MetaPref. This is a unique identifier. - * - * @return ID (unique) of MetaPref. - */ - public String getID() - { - return m_id; - } - - /** - * Gets the Choices of a MetaPref. This is optional and may be null. - * - * @return ID (unique) of MetaPref. - */ - public ArrayList> getChoices() - { - return choices; - } - - /** - * Returns true if the metaPref has choices. False otherwise - * - * @return - */ - public boolean hasChoices() - { - return choices != null; - } - - /** - * Get a Choice from the list of choices, whose value matches the value passed in. - * - * @param value - * Value to find - * @return Choice whose value equals the passed in value - */ - public Choice getChoiceByValue(String value) - { - if (choiceList == null) - populateChoiceList(); - return choiceList.get(value); - } - - /** - * Get Choice's name, for a choice whose value that matches the given value. - * - * @param value - * @return Name of choice - */ - public String getChoiceNameByValue(String value) - { - return getChoiceByValue(value).getName(); - } - - /** - * Get Choice's name, for the choice at the given index. - * - * @param index - * @return Name of choice - */ - public String getChoiceNameByIndex(int index) - { - return choices.get(index).getName(); - } - - /** - * Get the Choice at the given index. - * - * @param index - * @return Name of choice - */ - public Choice getChoiceByIndex(int index) - { - return choices.get(index); - } - - /** - * Get the index of a given Choice. - * - * @param choice - * Given choice - * @return Index of Choice in choices - */ - public int getIndexByChoice(Choice choice) - { - if (choiceList == null) - populateChoiceList(); - return choices.indexOf(choice); - } - - /** - * Get the index of a Choice with the given value. - * - * @param value - * @return index of Choice with given value - */ - public int getIndexByValue(String value) - { - Choice thisChoice = getChoiceByValue(value); - return getIndexByChoice(thisChoice); - } - - /** - * Populate choiceList; this allows for easy searching by value. - */ - private void populateChoiceList() - { - choiceList = new LinkedHashMap>(); - for (Choice choice : this.choices) - { - choiceList.put(choice.getValue().toString(), choice); - } - } - - /** - * Gives printed output showing id, description, category, helpText, widget, default value, and - * choices for a MetaPref. - */ - public void print() - { - println(this.m_id + '\n' + this.description + '\n' + this.category + '\n' + this.helpText - + '\n' + this.widget); - println("" + this.getDefaultValue()); - if (choices != null) - { - for (Choice choice : choices) - { - println("Choice: " + choice.name + ", " + choice.label); - } - } - println("\n"); - } - - /** - * Returns whether or not a widget uses radio buttons. - * - * @return True = Uses radio buttons. False = Doesn't. - */ - public boolean widgetIsRadio() - { - if (RADIO_BUTTONS.equals(widget)) - return true; - return false; - } - - /** - * Returns whether or not a widget uses a slider. - * - * @return True = Uses a slider. False = Doesn't. - */ - public boolean widgetIsSlider() - { - if (SLIDER.equals(widget)) - return true; - return false; - } - - /** - * Returns whether or not a widget uses a spinner. - * - * @return True = Uses a spinner. False = Doesn't. - */ - public boolean widgetIsSpinner() - { - if (SPINNER.equals(widget)) - return true; - return false; - } - - /** - * Returns whether or not a widget uses one or more text fields. - * - * @return True = Uses text field(s). False = Doesn't. - */ - public boolean widgetIsTextField() - { - if (TEXT_FIELD.equals(widget)) - return true; - return false; - } - - /** - * Returns whether or not a widget uses check boxes. - * - * @return True = Uses check boxes. False = Doesn't. - */ - public boolean widgetIsCheckBox() - { - if (CHECK_BOX.equals(widget)) - return true; - return false; - } - - /** - * Returns whether or not a widget uses a drop down menu. - * - * @return True = Uses a drop down menu. False = Doesn't. - */ - public boolean widgetIsDropDown() - { - if (DROP_DOWN.equals(widget)) - return true; - return false; - } - - /** - * Returns whether or not a widget uses a color chooser. - * - * @return True = Uses a color chooser. False = Doesn't. - */ - public boolean widgetIsColorChooser() - { - if (COLOR_CHOOSER.equals(widget)) - return true; - return false; - } - - /** - * Returns whether or not a widget uses a file chooser. - * - * @return True = Uses a file chooser. False = Doesn't. - */ - public boolean widgetIsFileChooser() - { - if (FILE_CHOOSER.equals(widget)) - return true; - return false; - } - - /** - * Construct a new instance of the Pref that matches this. - * - * @return - */ - protected abstract Pref getPrefInstance(); - - /** - * Create an instance of our associated type, from a String. - * - * @param string - * @return - */ - public T getInstance(String string) - { - return scalarType.getInstance(string); - } - - public T getInstance(T value) - { - return value; - } - - /** - * Construct a new instance of the Pref that matches this. Use this to fill-in the default value. - * - * @return - */ - public Pref getDefaultPrefInstance() - { - Pref result = getPrefInstance(); - result.name = m_id; - - result.setValue(this.getDefaultValue()); - return result; - } - - /** - * Get the Pref object associated with this. That is, look for one in the registry. Return it if - * there is one. Otherwise, get a default Pref based on this, register it, and return it. - * - * @return The Pref object associated with this MetaPref. - */ - public Pref getAssociatedPref() - { - Pref result = Pref.lookupPref(m_id); - if (result == null) - { - result = getDefaultPrefInstance(); - result.register(); - } - return result; - } - - /** - * Set object that receives a callback when the value of a Pref is changed through the - * PrefsEditor. - * - * @param valueChangedListener - */ - public void setValueChangedListener(ValueChangedListener valueChangedListener) - { - this.valueChangedListener = valueChangedListener; - } - - /** - * Set object that receives a callback when the value of a Pref is changed through the - * PrefsEditor. - * - * @param valueChangedListener - */ - public static void setValueChangedListener(String metaPrefId, - ValueChangedListener valueChangedListener) - { - MetaPref metaPref = lookup(metaPrefId); - if (metaPref != null) - metaPref.setValueChangedListener(valueChangedListener); - } - - /** - * Create an entry for this in the allMetaPrefsMap. - * - */ - void register() - { - allMetaPrefsMap.put(this.m_id, this); - } - - /** - * Look up a MetaPref by name in the map of all MetaPrefs - * - * @param id - * Name of MetaPref - * - * @return MetaPref with the given id - */ - public static MetaPref lookup(String id) - { - MetaPref metaPref = allMetaPrefsMap.get(id); - return metaPref; - } - - public ValueChangedListener getValueChangedListener() - { - return valueChangedListener; - } - - @Override - public void deserializationPostHook(TranslationContext translationContext, Object object) - { - MetaPref metaPref = (MetaPref) object; - - if (metaPref.parent() instanceof MetaPrefSet) - { - ((MetaPrefSet) metaPref.parent()).addEntryToCategoryMap(metaPref); - metaPref.getAssociatedPref(); // create one if needed - } - else - { - weird("parent of metaPref should be MetaPrefSet."); - } - } - - /* - * public boolean isWithinRange(T newValue) { return (range == null) ? true : - * range.isWithinRange(newValue); } - */ - -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import java.util.ArrayList; +import java.util.LinkedHashMap; + +import ecologylab.collections.Scope; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_classes; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.types.ScalarType; + +/** + * Metadata about a Preference. Defines information to enable editing the Preference. + * + * @author andruid + * + */ + +@simpl_inherit +public abstract class MetaPref extends ElementState implements WidgetTypes +{ + /** The global registry of Pref objects. Used for providing lookup services. */ + static final Scope allMetaPrefsMap = new Scope(); + + /** + * Unique identifier for Preference name with convenient lookup in automatically generated + * HashMap. + */ + @simpl_tag("id") + @simpl_scalar + String m_id; + + /** + * This is the short text that appears in the Swing panel for editing the value. + */ + @simpl_scalar + String description; + + /** + * This is longer text about that describes what the Preference does and more about the + * implications of its value. + */ + @simpl_scalar + String helpText; + + /** + * Type of graphical user interface component used to interact with it. Must be a constant defined + * in the interface WidgetTypes If this value is left as null, it should default to TEXT_FIELD. + */ + @simpl_scalar + String widget; + + /** + * Categories enable tabbed panes of preferences to be edited. + */ + @simpl_scalar + String category; + + /** + * Whether or not the application has to restart for this pref change to take effect. + */ + @simpl_scalar + boolean requiresRestart; + + /** + * optional; for preferences with three or more choices + */ + @simpl_collection + @simpl_classes( + { ChoiceBoolean.class, ChoiceFloat.class, ChoiceInt.class }) + ArrayList> choices; + + ScalarType scalarType; + + /** + * LinkedHashMap to make locating exact choices easier + */ + private LinkedHashMap> choiceList; + + ValueChangedListener valueChangedListener; + + // @xml_attribute T defaultValue; + + // @xml_nested RangeState range; + /** + * Instantiate. + * + * @param scalarType + * TODO + */ + public MetaPref(ScalarType scalarType) + { + super(); + this.scalarType = scalarType; + } + + /** + * Gets the default value of a MetaPref; type-specific behavior. + * + * @return Default value of MetaPref + */ + public abstract T getDefaultValue(); + + /** + * Gets the min value of the range of a MetaPref. + * + * @return Min value of a MetaPref + */ + public abstract T getMinValue(); + + /** + * Gets the max value of the range of a MetaPref. + * + * @return Max value of a MetaPref + */ + public abstract T getMaxValue(); + + /** + * Gets the category for a MetaPref. + * + * @return Category of MetaPref + */ + public String getCategory() + { + return category; + } + + /** + * Gets the description for a MetaPref. + * + * @return Description of MetaPref + */ + public String getDescription() + { + String result = description; + if (requiresRestart) + result += "
Requires restart to take effect."; + return result; + } + + /** + * Gets the help text for a MetaPref. + * + * @return Help Text of MetaPref + */ + public String getHelpText() + { + return helpText; + } + + /** + * Gets the ID of a MetaPref. This is a unique identifier. + * + * @return ID (unique) of MetaPref. + */ + public String getID() + { + return m_id; + } + + /** + * Gets the Choices of a MetaPref. This is optional and may be null. + * + * @return ID (unique) of MetaPref. + */ + public ArrayList> getChoices() + { + return choices; + } + + /** + * Returns true if the metaPref has choices. False otherwise + * + * @return + */ + public boolean hasChoices() + { + return choices != null; + } + + /** + * Get a Choice from the list of choices, whose value matches the value passed in. + * + * @param value + * Value to find + * @return Choice whose value equals the passed in value + */ + public Choice getChoiceByValue(String value) + { + if (choiceList == null) + populateChoiceList(); + return choiceList.get(value); + } + + /** + * Get Choice's name, for a choice whose value that matches the given value. + * + * @param value + * @return Name of choice + */ + public String getChoiceNameByValue(String value) + { + return getChoiceByValue(value).getName(); + } + + /** + * Get Choice's name, for the choice at the given index. + * + * @param index + * @return Name of choice + */ + public String getChoiceNameByIndex(int index) + { + return choices.get(index).getName(); + } + + /** + * Get the Choice at the given index. + * + * @param index + * @return Name of choice + */ + public Choice getChoiceByIndex(int index) + { + return choices.get(index); + } + + /** + * Get the index of a given Choice. + * + * @param choice + * Given choice + * @return Index of Choice in choices + */ + public int getIndexByChoice(Choice choice) + { + if (choiceList == null) + populateChoiceList(); + return choices.indexOf(choice); + } + + /** + * Get the index of a Choice with the given value. + * + * @param value + * @return index of Choice with given value + */ + public int getIndexByValue(String value) + { + Choice thisChoice = getChoiceByValue(value); + return getIndexByChoice(thisChoice); + } + + /** + * Populate choiceList; this allows for easy searching by value. + */ + private void populateChoiceList() + { + choiceList = new LinkedHashMap>(); + for (Choice choice : this.choices) + { + choiceList.put(choice.getValue().toString(), choice); + } + } + + /** + * Gives printed output showing id, description, category, helpText, widget, default value, and + * choices for a MetaPref. + */ + public void print() + { + println(this.m_id + '\n' + this.description + '\n' + this.category + '\n' + this.helpText + + '\n' + this.widget); + println("" + this.getDefaultValue()); + if (choices != null) + { + for (Choice choice : choices) + { + println("Choice: " + choice.name + ", " + choice.label); + } + } + println("\n"); + } + + /** + * Returns whether or not a widget uses radio buttons. + * + * @return True = Uses radio buttons. False = Doesn't. + */ + public boolean widgetIsRadio() + { + if (RADIO_BUTTONS.equals(widget)) + return true; + return false; + } + + /** + * Returns whether or not a widget uses a slider. + * + * @return True = Uses a slider. False = Doesn't. + */ + public boolean widgetIsSlider() + { + if (SLIDER.equals(widget)) + return true; + return false; + } + + /** + * Returns whether or not a widget uses a spinner. + * + * @return True = Uses a spinner. False = Doesn't. + */ + public boolean widgetIsSpinner() + { + if (SPINNER.equals(widget)) + return true; + return false; + } + + /** + * Returns whether or not a widget uses one or more text fields. + * + * @return True = Uses text field(s). False = Doesn't. + */ + public boolean widgetIsTextField() + { + if (TEXT_FIELD.equals(widget)) + return true; + return false; + } + + /** + * Returns whether or not a widget uses check boxes. + * + * @return True = Uses check boxes. False = Doesn't. + */ + public boolean widgetIsCheckBox() + { + if (CHECK_BOX.equals(widget)) + return true; + return false; + } + + /** + * Returns whether or not a widget uses a drop down menu. + * + * @return True = Uses a drop down menu. False = Doesn't. + */ + public boolean widgetIsDropDown() + { + if (DROP_DOWN.equals(widget)) + return true; + return false; + } + + /** + * Returns whether or not a widget uses a color chooser. + * + * @return True = Uses a color chooser. False = Doesn't. + */ + public boolean widgetIsColorChooser() + { + if (COLOR_CHOOSER.equals(widget)) + return true; + return false; + } + + /** + * Returns whether or not a widget uses a file chooser. + * + * @return True = Uses a file chooser. False = Doesn't. + */ + public boolean widgetIsFileChooser() + { + if (FILE_CHOOSER.equals(widget)) + return true; + return false; + } + + /** + * Construct a new instance of the Pref that matches this. + * + * @return + */ + protected abstract Pref getPrefInstance(); + + /** + * Create an instance of our associated type, from a String. + * + * @param string + * @return + */ + public T getInstance(String string) + { + return scalarType.getInstance(string); + } + + public T getInstance(T value) + { + return value; + } + + /** + * Construct a new instance of the Pref that matches this. Use this to fill-in the default value. + * + * @return + */ + public Pref getDefaultPrefInstance() + { + Pref result = getPrefInstance(); + result.name = m_id; + + result.setValue(this.getDefaultValue()); + return result; + } + + /** + * Get the Pref object associated with this. That is, look for one in the registry. Return it if + * there is one. Otherwise, get a default Pref based on this, register it, and return it. + * + * @return The Pref object associated with this MetaPref. + */ + public Pref getAssociatedPref() + { + Pref result = Pref.lookupPref(m_id); + if (result == null) + { + result = getDefaultPrefInstance(); + result.register(); + } + return result; + } + + /** + * Set object that receives a callback when the value of a Pref is changed through the + * PrefsEditor. + * + * @param valueChangedListener + */ + public void setValueChangedListener(ValueChangedListener valueChangedListener) + { + this.valueChangedListener = valueChangedListener; + } + + /** + * Set object that receives a callback when the value of a Pref is changed through the + * PrefsEditor. + * + * @param valueChangedListener + */ + public static void setValueChangedListener(String metaPrefId, + ValueChangedListener valueChangedListener) + { + MetaPref metaPref = lookup(metaPrefId); + if (metaPref != null) + metaPref.setValueChangedListener(valueChangedListener); + } + + /** + * Create an entry for this in the allMetaPrefsMap. + * + */ + void register() + { + allMetaPrefsMap.put(this.m_id, this); + } + + /** + * Look up a MetaPref by name in the map of all MetaPrefs + * + * @param id + * Name of MetaPref + * + * @return MetaPref with the given id + */ + public static MetaPref lookup(String id) + { + MetaPref metaPref = allMetaPrefsMap.get(id); + return metaPref; + } + + public ValueChangedListener getValueChangedListener() + { + return valueChangedListener; + } + + @Override + public void deserializationPostHook(TranslationContext translationContext, Object object) + { + MetaPref metaPref = (MetaPref) object; + + if (metaPref.parent() instanceof MetaPrefSet) + { + ((MetaPrefSet) metaPref.parent()).addEntryToCategoryMap(metaPref); + metaPref.getAssociatedPref(); // create one if needed + } + else + { + weird("parent of metaPref should be MetaPrefSet."); + } + } + + /* + * public boolean isWithinRange(T newValue) { return (range == null) ? true : + * range.isWithinRange(newValue); } + */ + +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefBoolean.java b/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefBoolean.java index cdc9774e..2abdea14 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefBoolean.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefBoolean.java @@ -1,92 +1,92 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.TypeRegistry; - -/** - * Metadata about a Boolean Preference. - * Defines information to enable editing the Preference. - * - * @author andruid - * - */ -@simpl_inherit -public class MetaPrefBoolean extends MetaPref -{ - /** - * Default value for this MetaPref - */ - @simpl_scalar boolean defaultValue; - - public static final ScalarType BOOLEAN_SCALAR_TYPE = TypeRegistry.getScalarType(boolean.class); - - /** - * Instantiate. - */ - public MetaPrefBoolean() - { - super(BOOLEAN_SCALAR_TYPE); - } - - /** - * Gets the default value of a MetaPref. - * - * @return Default value of MetaPref - */ - @Override - public Boolean getDefaultValue() - { - return defaultValue; - } - - /** - * Construct a new instance of the Pref that matches this. - * Use this to fill-in the default value. - * - * @return new Pref instance - */ - protected @Override Pref getPrefInstance() - { - return new PrefBoolean(); - } - - /** - * Get max value; returns null for this type. - */ - @Override - public Boolean getMaxValue() - { - return null; - } - - /** - * Get min value; returns null for this type. - */ - @Override - public Boolean getMinValue() - { - return null; - } - - /** - * Get the current PrefBoolean object associated with this. - * If there is not one yet, create one with the default value specified in this. - * - * @return - */ - public PrefBoolean usePrefBoolean() - { - return Pref.usePrefBoolean(getID(), getDefaultValue()); - } -/* - public boolean isWithinRange(Boolean newValue) - { - return (range == null) ? true : range.isWithinRange(newValue); - } - */ +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.TypeRegistry; + +/** + * Metadata about a Boolean Preference. + * Defines information to enable editing the Preference. + * + * @author andruid + * + */ +@simpl_inherit +public class MetaPrefBoolean extends MetaPref +{ + /** + * Default value for this MetaPref + */ + @simpl_scalar boolean defaultValue; + + public static final ScalarType BOOLEAN_SCALAR_TYPE = TypeRegistry.getScalarType(boolean.class); + + /** + * Instantiate. + */ + public MetaPrefBoolean() + { + super(BOOLEAN_SCALAR_TYPE); + } + + /** + * Gets the default value of a MetaPref. + * + * @return Default value of MetaPref + */ + @Override + public Boolean getDefaultValue() + { + return defaultValue; + } + + /** + * Construct a new instance of the Pref that matches this. + * Use this to fill-in the default value. + * + * @return new Pref instance + */ + protected @Override Pref getPrefInstance() + { + return new PrefBoolean(); + } + + /** + * Get max value; returns null for this type. + */ + @Override + public Boolean getMaxValue() + { + return null; + } + + /** + * Get min value; returns null for this type. + */ + @Override + public Boolean getMinValue() + { + return null; + } + + /** + * Get the current PrefBoolean object associated with this. + * If there is not one yet, create one with the default value specified in this. + * + * @return + */ + public PrefBoolean usePrefBoolean() + { + return Pref.usePrefBoolean(getID(), getDefaultValue()); + } +/* + public boolean isWithinRange(Boolean newValue) + { + return (range == null) ? true : range.isWithinRange(newValue); + } + */ } \ No newline at end of file diff --git a/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefFile.java b/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefFile.java index 012d6986..09f231aa 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefFile.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefFile.java @@ -1,108 +1,108 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import java.io.File; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.TypeRegistry; - -/** - * Metadata about a File Preference. - * Defines information to enable editing the Preference. - * - * @author andruid - * - */ - -@simpl_inherit -public class MetaPrefFile extends MetaPref -{ - /** - * Default value for this MetaPref - */ - @simpl_scalar File defaultValue; - @simpl_scalar int pathContext = ABSOLUTE_PATH; - - /** Indicates that value is an absolute path. */ - public static final int ABSOLUTE_PATH = 0; - - /** - * Indicates that value is a path relative to the codebase of the - * application using this Pref. - */ - public static final int CODE_BASE = 1; - - /** - * Indicates that value is a path relative to the data directory associated - * with the application using this Pref. - */ - public static final int APP_DATA_DIR = 2; - - public static final ScalarType FILE_SCALAR_TYPE = TypeRegistry.getScalarType(File.class); - - /** - * Instantiate. - */ - public MetaPrefFile() - { - super(FILE_SCALAR_TYPE); - } - - /** - * Gets the default value of a MetaPref. - * - * @return Default value of MetaPref - */ - @Override - public File getDefaultValue() - { - return defaultValue; - } - - /** - * Construct a new instance of the Pref that matches this. - * Use this to fill-in the default value. - * - * @return - */ - protected @Override Pref getPrefInstance() - { - return new PrefFile(); - } - - /** - * Get max value; returns null for this type. - */ - @Override - public File getMaxValue() - { - return null; - } - - /** - * Get min value; returns null for this type. - */ - @Override - public File getMinValue() - { - return null; - } - -// @Override -// public File getInstance(String string) -// { -// return new File(string); -// } - - -/* - public boolean isWithinRange(File newValue) - { - return (range == null) ? true : range.isWithinRange(newValue); - } - */ +/** + * + */ +package ecologylab.appframework.types.prefs; + +import java.io.File; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.TypeRegistry; + +/** + * Metadata about a File Preference. + * Defines information to enable editing the Preference. + * + * @author andruid + * + */ + +@simpl_inherit +public class MetaPrefFile extends MetaPref +{ + /** + * Default value for this MetaPref + */ + @simpl_scalar File defaultValue; + @simpl_scalar int pathContext = ABSOLUTE_PATH; + + /** Indicates that value is an absolute path. */ + public static final int ABSOLUTE_PATH = 0; + + /** + * Indicates that value is a path relative to the codebase of the + * application using this Pref. + */ + public static final int CODE_BASE = 1; + + /** + * Indicates that value is a path relative to the data directory associated + * with the application using this Pref. + */ + public static final int APP_DATA_DIR = 2; + + public static final ScalarType FILE_SCALAR_TYPE = TypeRegistry.getScalarType(File.class); + + /** + * Instantiate. + */ + public MetaPrefFile() + { + super(FILE_SCALAR_TYPE); + } + + /** + * Gets the default value of a MetaPref. + * + * @return Default value of MetaPref + */ + @Override + public File getDefaultValue() + { + return defaultValue; + } + + /** + * Construct a new instance of the Pref that matches this. + * Use this to fill-in the default value. + * + * @return + */ + protected @Override Pref getPrefInstance() + { + return new PrefFile(); + } + + /** + * Get max value; returns null for this type. + */ + @Override + public File getMaxValue() + { + return null; + } + + /** + * Get min value; returns null for this type. + */ + @Override + public File getMinValue() + { + return null; + } + +// @Override +// public File getInstance(String string) +// { +// return new File(string); +// } + + +/* + public boolean isWithinRange(File newValue) + { + return (range == null) ? true : range.isWithinRange(newValue); + } + */ } \ No newline at end of file diff --git a/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefFloat.java b/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefFloat.java index b7f2e123..312cb42f 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefFloat.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefFloat.java @@ -1,101 +1,101 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.TypeRegistry; - -/** - * Metadata about a Float Preference. - * Defines information to enable editing the Preference. - * - * @author andruid - * - */ - -@simpl_inherit -public class MetaPrefFloat extends MetaPref -{ - /** - * Default value for this MetaPref - */ - @simpl_scalar float defaultValue; - /** - * Min/max values - */ - @simpl_composite RangeFloatState range; - - public static final ScalarType FLOAT_SCALAR_TYPE = TypeRegistry.getScalarType(float.class); - - /** - * Instantiate. - */ - public MetaPrefFloat() - { - super(FLOAT_SCALAR_TYPE); - } - - /** - * Gets the default value of a MetaPref. - * - * @return Default value of MetaPref - */ - @Override - public Float getDefaultValue() - { - return defaultValue; - } - - /** - * Construct a new instance of the Pref that matches this. - * Use this to fill-in the default value. - * - * @return - */ - protected @Override Pref getPrefInstance() - { - return new PrefFloat(); - } - - /** - * Get max value for this MetaPref; returns null if it is not defined. - */ - @Override - public Float getMaxValue() - { - if (range != null) - return range.getMax(); - else - return null; - } - - /** - * Get min value for this MetaPref; returns null if it is not defined. - */ - @Override - public Float getMinValue() - { - if (range != null) - return range.getMin(); - else - return null; - } - -// @Override -// public Float getInstance(String string) -// { -// // return scalarType.getInstance(string); -// return new Float(string); -// } - -/* - public boolean isWithinRange(Float newValue) - { - return (range == null) ? true : range.isWithinRange(newValue); - } - */ +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.TypeRegistry; + +/** + * Metadata about a Float Preference. + * Defines information to enable editing the Preference. + * + * @author andruid + * + */ + +@simpl_inherit +public class MetaPrefFloat extends MetaPref +{ + /** + * Default value for this MetaPref + */ + @simpl_scalar float defaultValue; + /** + * Min/max values + */ + @simpl_composite RangeFloatState range; + + public static final ScalarType FLOAT_SCALAR_TYPE = TypeRegistry.getScalarType(float.class); + + /** + * Instantiate. + */ + public MetaPrefFloat() + { + super(FLOAT_SCALAR_TYPE); + } + + /** + * Gets the default value of a MetaPref. + * + * @return Default value of MetaPref + */ + @Override + public Float getDefaultValue() + { + return defaultValue; + } + + /** + * Construct a new instance of the Pref that matches this. + * Use this to fill-in the default value. + * + * @return + */ + protected @Override Pref getPrefInstance() + { + return new PrefFloat(); + } + + /** + * Get max value for this MetaPref; returns null if it is not defined. + */ + @Override + public Float getMaxValue() + { + if (range != null) + return range.getMax(); + else + return null; + } + + /** + * Get min value for this MetaPref; returns null if it is not defined. + */ + @Override + public Float getMinValue() + { + if (range != null) + return range.getMin(); + else + return null; + } + +// @Override +// public Float getInstance(String string) +// { +// // return scalarType.getInstance(string); +// return new Float(string); +// } + +/* + public boolean isWithinRange(Float newValue) + { + return (range == null) ? true : range.isWithinRange(newValue); + } + */ } \ No newline at end of file diff --git a/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefInt.java b/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefInt.java index a6a405f3..47d6fe97 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefInt.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefInt.java @@ -1,93 +1,93 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.TypeRegistry; -/** - * Metadata about an Integer Preference. - * Defines information to enable editing the Preference. - * - * @author andruid - * - */ -@simpl_inherit -public class MetaPrefInt extends MetaPref -{ - /** - * Default value for this MetaPref - */ - @simpl_scalar int defaultValue; - - /** - * Min/max values - */ - @simpl_composite RangeIntState range; - - public static final ScalarType INT_SCALAR_TYPE = TypeRegistry.getScalarType(int.class); - - /** - * Instantiate. - */ - public MetaPrefInt() - { - super(INT_SCALAR_TYPE); - } - - /** - * Gets the default value of a MetaPref. - * - * @return Default value of MetaPref - */ - @Override - public Integer getDefaultValue() - { - return defaultValue; - } - - /** - * Construct a new instance of the Pref that matches this. - * Use this to fill-in the default value. - * - * @return - */ - protected @Override Pref getPrefInstance() - { - return new PrefInt(); - } - - /** - * Get max value for this MetaPref; returns null if it is not defined. - */ - @Override - public Integer getMaxValue() - { - if (range != null) - return range.getMax(); - else - return null; - } - - /** - * Get min value for this MetaPref; returns null if it is not defined. - */ - @Override - public Integer getMinValue() - { - if (range != null) - return range.getMin(); - else - return null; - } - -/* - public boolean isWithinRange(Integer newValue) - { - return (range == null) ? true : range.isWithinRange(newValue); - } - */ +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.TypeRegistry; +/** + * Metadata about an Integer Preference. + * Defines information to enable editing the Preference. + * + * @author andruid + * + */ +@simpl_inherit +public class MetaPrefInt extends MetaPref +{ + /** + * Default value for this MetaPref + */ + @simpl_scalar int defaultValue; + + /** + * Min/max values + */ + @simpl_composite RangeIntState range; + + public static final ScalarType INT_SCALAR_TYPE = TypeRegistry.getScalarType(int.class); + + /** + * Instantiate. + */ + public MetaPrefInt() + { + super(INT_SCALAR_TYPE); + } + + /** + * Gets the default value of a MetaPref. + * + * @return Default value of MetaPref + */ + @Override + public Integer getDefaultValue() + { + return defaultValue; + } + + /** + * Construct a new instance of the Pref that matches this. + * Use this to fill-in the default value. + * + * @return + */ + protected @Override Pref getPrefInstance() + { + return new PrefInt(); + } + + /** + * Get max value for this MetaPref; returns null if it is not defined. + */ + @Override + public Integer getMaxValue() + { + if (range != null) + return range.getMax(); + else + return null; + } + + /** + * Get min value for this MetaPref; returns null if it is not defined. + */ + @Override + public Integer getMinValue() + { + if (range != null) + return range.getMin(); + else + return null; + } + +/* + public boolean isWithinRange(Integer newValue) + { + return (range == null) ? true : range.isWithinRange(newValue); + } + */ } \ No newline at end of file diff --git a/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefSet.java b/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefSet.java index b9a13c1f..7d857e67 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefSet.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefSet.java @@ -1,197 +1,197 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Set; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_scope; -import ecologylab.serialization.formatenums.Format; -/** - * Groupings of MetaPrefs, by category. Categories - * are also ordered in a separate ArrayList. - * Contains functions related to adding MetaPrefs to the - * grouping, getting MetaPrefs, getting the categories, etc. - * - * @author Cae - * - */ - -@simpl_inherit -public class MetaPrefSet extends ElementState -{ - @simpl_scalar String title; - @simpl_scalar int width; - @simpl_scalar int height; - - @simpl_collection - @simpl_nowrap - @simpl_scope(MetaPrefsTranslationScope.NAME) - ArrayList metaPreferences; - - /** - * HashMap of category Strings to ArrayList of MetaPrefs. - */ - private HashMap> categoryToMetaPrefs = new HashMap>(); - /** - * ArrayList of category Strings, in the order they are gotten from - * the xml file. This is used to order the tabs in GUI creation. - */ - private ArrayList orderOfTabs = new ArrayList(); - - /** - * Perform custom processing on the newly created child node, - * just before it is added to this. - *

- * This is part of depth-first traversal during translateFromXML(). - *

- * Add the entry to the category map. - *

- * Also, create a Pref to match the MetaPref child, if there isn't one already. - * - * @param child - */ - @Override - protected void createChildHook(ElementState child) - { - MetaPref metaPref = (MetaPref) child; - addEntryToCategoryMap(metaPref); - metaPref.getAssociatedPref(); // create one if needed - } - - /** - * Add entry to the Category-MetaPrefs map. - * @param metaPref - */ - void addEntryToCategoryMap(MetaPref metaPref) - { - ArrayList metaPrefList = categoryToMetaPrefs.get(metaPref.getCategory()); - if (metaPrefList == null) - { - metaPrefList = new ArrayList(); - categoryToMetaPrefs.put(metaPref.category, metaPrefList); - orderOfTabs.add(metaPref.category); - } - metaPrefList.add(metaPref); - } - - /** - * - */ - public MetaPrefSet() - { - - } - - /** - * Return the ordered list of categories. - * - * @param tabList String Array that will hold category names. - * - * @return tabList String Array that will hold category names. - */ - public String[] getOrderedTabNames(String[] tabList) - { - return orderOfTabs.toArray(tabList); - } - - /** - * Return the number of categories. - * - * @return Number of categories - */ - public int getNumberOfTabs() - { - return orderOfTabs.size(); - } - - /** - * Get the category names in a Set of Strings. - * - * @return String Set of categories. - */ - public Set getCategories() - { - return categoryToMetaPrefs.keySet(); - } - - /** - * Get the MetaPref ArrayList for a category name. - * - * @param cat Name of category - * - * @return ArrayList of MetaPrefs - */ - public ArrayList getMetaPrefListByCategory(String cat) - { - return categoryToMetaPrefs.get(cat); - } - - /** - * Register the MetaPref in the static global map, as well as adding it to the super ArrayListState. - * @param metaPref - * @return - */ - public boolean add(MetaPref metaPref) - { - boolean result = metaPreferences.add(metaPref); - metaPref.register(); - return result; - } - - /** - * Read MetaPref declarations from a file or across the net. - * - * @param file - * @param translationScope - * @return - * @throws SIMPLTranslationException - */ - public static MetaPrefSet load(File file, SimplTypesScope translationScope) - throws SIMPLTranslationException - { - return load(new ParsedURL(file), translationScope); - - } - - /** - * Read MetaPref declarations from a file or across the net. - * - * @param purl - * @param translationScope - * @return - * @throws SIMPLTranslationException - */ - public static MetaPrefSet load(ParsedURL purl, SimplTypesScope translationScope) - throws SIMPLTranslationException - { - return (MetaPrefSet) translationScope.deserialize(purl, Format.XML); - - } - - public int getHeight() - { - return height; - } - - public String getTitle() - { - return title; - } - - public int getWidth() - { - return width; - } -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Set; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_scope; +import ecologylab.serialization.formatenums.Format; +/** + * Groupings of MetaPrefs, by category. Categories + * are also ordered in a separate ArrayList. + * Contains functions related to adding MetaPrefs to the + * grouping, getting MetaPrefs, getting the categories, etc. + * + * @author Cae + * + */ + +@simpl_inherit +public class MetaPrefSet extends ElementState +{ + @simpl_scalar String title; + @simpl_scalar int width; + @simpl_scalar int height; + + @simpl_collection + @simpl_nowrap + @simpl_scope(MetaPrefsTranslationScope.NAME) + ArrayList metaPreferences; + + /** + * HashMap of category Strings to ArrayList of MetaPrefs. + */ + private HashMap> categoryToMetaPrefs = new HashMap>(); + /** + * ArrayList of category Strings, in the order they are gotten from + * the xml file. This is used to order the tabs in GUI creation. + */ + private ArrayList orderOfTabs = new ArrayList(); + + /** + * Perform custom processing on the newly created child node, + * just before it is added to this. + *

+ * This is part of depth-first traversal during translateFromXML(). + *

+ * Add the entry to the category map. + *

+ * Also, create a Pref to match the MetaPref child, if there isn't one already. + * + * @param child + */ + @Override + protected void createChildHook(ElementState child) + { + MetaPref metaPref = (MetaPref) child; + addEntryToCategoryMap(metaPref); + metaPref.getAssociatedPref(); // create one if needed + } + + /** + * Add entry to the Category-MetaPrefs map. + * @param metaPref + */ + void addEntryToCategoryMap(MetaPref metaPref) + { + ArrayList metaPrefList = categoryToMetaPrefs.get(metaPref.getCategory()); + if (metaPrefList == null) + { + metaPrefList = new ArrayList(); + categoryToMetaPrefs.put(metaPref.category, metaPrefList); + orderOfTabs.add(metaPref.category); + } + metaPrefList.add(metaPref); + } + + /** + * + */ + public MetaPrefSet() + { + + } + + /** + * Return the ordered list of categories. + * + * @param tabList String Array that will hold category names. + * + * @return tabList String Array that will hold category names. + */ + public String[] getOrderedTabNames(String[] tabList) + { + return orderOfTabs.toArray(tabList); + } + + /** + * Return the number of categories. + * + * @return Number of categories + */ + public int getNumberOfTabs() + { + return orderOfTabs.size(); + } + + /** + * Get the category names in a Set of Strings. + * + * @return String Set of categories. + */ + public Set getCategories() + { + return categoryToMetaPrefs.keySet(); + } + + /** + * Get the MetaPref ArrayList for a category name. + * + * @param cat Name of category + * + * @return ArrayList of MetaPrefs + */ + public ArrayList getMetaPrefListByCategory(String cat) + { + return categoryToMetaPrefs.get(cat); + } + + /** + * Register the MetaPref in the static global map, as well as adding it to the super ArrayListState. + * @param metaPref + * @return + */ + public boolean add(MetaPref metaPref) + { + boolean result = metaPreferences.add(metaPref); + metaPref.register(); + return result; + } + + /** + * Read MetaPref declarations from a file or across the net. + * + * @param file + * @param translationScope + * @return + * @throws SIMPLTranslationException + */ + public static MetaPrefSet load(File file, SimplTypesScope translationScope) + throws SIMPLTranslationException + { + return load(new ParsedURL(file), translationScope); + + } + + /** + * Read MetaPref declarations from a file or across the net. + * + * @param purl + * @param translationScope + * @return + * @throws SIMPLTranslationException + */ + public static MetaPrefSet load(ParsedURL purl, SimplTypesScope translationScope) + throws SIMPLTranslationException + { + return (MetaPrefSet) translationScope.deserialize(purl, Format.XML); + + } + + public int getHeight() + { + return height; + } + + public String getTitle() + { + return title; + } + + public int getWidth() + { + return width; + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefString.java b/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefString.java index 4dd6a95f..06f5d4d0 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefString.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/MetaPrefString.java @@ -1,89 +1,89 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.TypeRegistry; - -/** - * Metadata about a String Preference. - * Defines information to enable editing the Preference. - * - * @author andruid - * - */ - -@simpl_inherit -public class MetaPrefString extends MetaPref -{ - /** - * Default value for this MetaPref - */ - @simpl_scalar String defaultValue; - - public static final ScalarType STRING_SCALAR_TYPE = TypeRegistry.getScalarType(String.class); - - /** - * Instantiate. - */ - public MetaPrefString() - { - super(STRING_SCALAR_TYPE); - } - - /** - * Gets the default value of a MetaPref. - * - * @return Default value of MetaPref - */ - @Override - public String getDefaultValue() - { - return defaultValue; - } - - /** - * Construct a new instance of the Pref that matches this. - * Use this to fill-in the default value. - * - * @return - */ - protected @Override Pref getPrefInstance() - { - return new PrefString(); - } - - /** - * Get max value; returns null for this type. - */ - @Override - public String getMaxValue() - { - return null; - } - - /** - * Get min value; returns null for this type. - */ - @Override - public String getMinValue() - { - return null; - } - - @Override - public String getInstance(String string) - { - return string; - } - -/* - public boolean isWithinRange(String newValue) - { - return (range == null) ? true : range.isWithinRange(newValue); - } - */ +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.TypeRegistry; + +/** + * Metadata about a String Preference. + * Defines information to enable editing the Preference. + * + * @author andruid + * + */ + +@simpl_inherit +public class MetaPrefString extends MetaPref +{ + /** + * Default value for this MetaPref + */ + @simpl_scalar String defaultValue; + + public static final ScalarType STRING_SCALAR_TYPE = TypeRegistry.getScalarType(String.class); + + /** + * Instantiate. + */ + public MetaPrefString() + { + super(STRING_SCALAR_TYPE); + } + + /** + * Gets the default value of a MetaPref. + * + * @return Default value of MetaPref + */ + @Override + public String getDefaultValue() + { + return defaultValue; + } + + /** + * Construct a new instance of the Pref that matches this. + * Use this to fill-in the default value. + * + * @return + */ + protected @Override Pref getPrefInstance() + { + return new PrefString(); + } + + /** + * Get max value; returns null for this type. + */ + @Override + public String getMaxValue() + { + return null; + } + + /** + * Get min value; returns null for this type. + */ + @Override + public String getMinValue() + { + return null; + } + + @Override + public String getInstance(String string) + { + return string; + } + +/* + public boolean isWithinRange(String newValue) + { + return (range == null) ? true : range.isWithinRange(newValue); + } + */ } \ No newline at end of file diff --git a/simplCore/src/ecologylab/appframework/types/prefs/Pref.java b/simplCore/src/ecologylab/appframework/types/prefs/Pref.java index 90efc1a7..28fcbb15 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/Pref.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/Pref.java @@ -1,674 +1,674 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -//import java.awt.Color; -import java.io.File; -import java.util.LinkedList; - -import ecologylab.appframework.SingletonApplicationEnvironment; -import ecologylab.collections.Scope; -import ecologylab.platformspecifics.FundamentalPlatformSpecifics; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.element.IMappable; - -/** - * Generic base class for application Preference objects. - * - * @author andruid - */ - -@simpl_inherit -public abstract class Pref extends ElementState implements IMappable, Cloneable -{ - /** The global registry of Pref objects. Used for providing lookup services. */ - static final Scope> allPrefsMap = new Scope>(); - - /** The ApplicationEnvironment associated with this JVM. */ - static final SingletonApplicationEnvironment aE = null; - - /** Name of a Pref; provides index into the preferences map. */ - @simpl_scalar - protected String name; - - /** Cached value */ - T valueCached; - - /** - * The list of PrefChangedListeners registered to respond to changes in Prefs. - */ - static LinkedList listeners = new LinkedList(); - - /** No-argument constructor for XML translation. */ - public Pref() - { - super(); - } - - protected Pref(String name) - { - this.name = name; - } - - /** - * Public generic accessor for the value. Caches autoboxed values, for efficiency. - * - * @return - */ - public T value() - { - T result = valueCached; - if (result == null) - { - result = getValue(); - valueCached = result; - } - return result; - } - - /** - * Print Pref name and value - */ - public void print() - { - println("Pref: name: " + name + ", value: " + this.getValue()); - } - - /** - * Return String of Pref name and value - * - * @return String of Pref name and value - */ - @Override - public String toString() - { - return "Pref: " + name + "(" + this.getValue() + ")"; - } - - /** - * Generic get value returns the value as the actual type you want. This version should only be - * called by value(), so that autoboxed types can be cached. This method *does not* do the - * caching. - * - * @return - */ - protected abstract T getValue(); - - /** - * Generic value setter. Uses boxed reference objects for primitives, which are a bit extra - * expensive. - * - * @param newValue - */ - public abstract void setValue(T newValue); - - /** - * Performs all housekeeping associated with updating this Pref. prefUpdated() should be called - * whenever the value of this has been changed. - * - * Notifies all listeners that the pref's value has changed. - * - * Set valueCached to null - */ - protected void prefChanged() - { - valueCached = null; - - Pref.firePrefChangedEvent(this); - } - - /** - * This is for working with Prefs whose values you will continue to access as they - * are edited, live, by the user. The result will be immediate changes in the program's behavior. - *

- * Lookup a Pref associated with name. If you find it return it. If not, create a new Pref object - * of the correct type. Set its value to default value. - * - * @param name - * Name of the Pref to lookup and find or create. - * @param defaultValue - * Initial value of the Pref if it didn't already exist. - * - * @return A usable Pref object associated with name, either from the registry or newly created - */ - public static PrefBoolean usePrefBoolean(String name, boolean defaultValue) - { - PrefBoolean pref = (PrefBoolean) lookupPref(name); - if (pref == null) - { - pref = new PrefBoolean(defaultValue); - pref.name = name; - pref.register(); - } - return pref; - } - - /** - * This is for working with Prefs whose values you will continue to access as they - * are edited, live, by the user. The result will be immediate changes in the program's behavior. - *

- * Lookup a Pref associated with name. If you find it return it. If not, create a new Pref object - * of the correct type. Set its value to default value. - * - * @param name - * Name of the Pref to lookup and find or create. - * @param defaultValue - * Initial value of the Pref if it didn't already exist. - * - * @return A usable Pref object associated with name, either from the registry or newly created - */ - public static PrefFloat usePrefFloat(String name, float defaultValue) - { - PrefFloat pref = (PrefFloat) lookupPref(name); - if (pref == null) - { - pref = new PrefFloat(defaultValue); - pref.name = name; - pref.register(); - } - return pref; - } - - /** - * This is for working with Prefs whose values you will continue to access as they - * are edited, live, by the user. The result will be immediate changes in the program's behavior. - *

- * Lookup a Pref associated with name. If you find it return it. If not, create a new Pref object - * of the correct type. Set its value to default value. - * - * @param name - * Name of the Pref to lookup and find or create. - * @param defaultValue - * Initial value of the Pref if it didn't already exist. - * - * @return A usable Pref object associated with name, either from the registry or newly created - */ - public static PrefString usePrefString(String name, String defaultValue) - { - PrefString pref = (PrefString) lookupPref(name); - if (pref == null) - { - pref = new PrefString(defaultValue); - pref.name = name; - pref.register(); - } - return pref; - } - - /** - * This is for working with Prefs whose values you will continue to access as they - * are edited, live, by the user. The result will be immediate changes in the program's behavior. - *

- * Lookup a Pref associated with name. If you find it return it. If not, create a new Pref object - * of the correct type. Set its value to default value. - * - * @param name - * Name of the Pref to lookup and find or create. - * @param defaultValue - * Initial value of the Pref if it didn't already exist. - * - * @return A usable Pref object associated with name, either from the registry or newly created - */ - public static PrefInt usePrefInt(String name, int defaultValue) - { - PrefInt pref = (PrefInt) lookupPref(name); - if (pref == null) - { - pref = new PrefInt(defaultValue); - pref.name = name; - pref.register(); - } - return pref; - } - - /** - * Lookup a Pref associated with name. If you find it, it is the operative Pref If not, create a - * new Pref object of the correct type, and register it. - *

- * Set the value of the operative Pref to that passed in here. - * - * @param name - * Name of the Pref to lookup and find or create. - * @param defaultValue - * Initial value of the Pref if it didn't already exist. - */ - public static void useAndSetPrefInt(String name, int value) - { - PrefInt thatPrefInt = usePrefInt(name, value); - thatPrefInt.setValue(value); - } - - public static void useAndSetPrefEnum(String name, Enum value) - { - PrefEnum thatPrefEnum = usePrefEnum(name, value); - thatPrefEnum.setValue(value); - } - - /** - * This is for working with Prefs whose values you will continue to access as they - * are edited, live, by the user. The result will be immediate changes in the program's behavior. - *

- * Lookup a Pref associated with name. If you find it return it. If not, create a new Pref object - * of the correct type. Set its value to default value. - * - * @param name - * Name of the Pref to lookup and find or create. - * @param defaultValue - * Initial value of the Pref if it didn't already exist. - * - * @return A usable Pref object associated with name, either from the registry or newly created - */ - public static Object usePrefColor(String name, Object defaultValue) - { - return FundamentalPlatformSpecifics.get().usePrefColor(name, defaultValue); - } - - /** - * This is for working with Prefs whose values you will continue to access as they - * are edited, live, by the user. The result will be immediate changes in the program's behavior. - *

- * Lookup a Pref associated with name. If you find it return it. If not, create a new Pref object - * of the correct type. Set its value to default value. - * - * @param name - * Name of the Pref to lookup and find or create. - * @param defaultValue - * Initial value of the Pref if it didn't already exist. - * - * @return A usable Pref object associated with name, either from the registry or newly created - */ - public static PrefEnum usePrefEnum(String name, Enum defaultValue) - { - PrefEnum pref = (PrefEnum) lookupPref(name); - if (pref == null) - { - pref = new PrefEnum(defaultValue); - pref.name = name; - pref.register(); - } - return pref; - } - - /** - * Look up a Pref by name in the map of all Prefs - * - * @param name - * Name of Pref - * - * @return Pref with the given name - */ - public static Pref lookupPref(String name) - { - Pref pref = allPrefsMap.get(name); - return pref; - } - - public static void printAllPrefsMap() - { - for (Pref p : allPrefsMap.values()) - { - System.out.println("PREF: " + p.getName() + " = " + p.value()); - } - } - - /** - * Turn the entry for a pref name to null in the global map. - * - * @param name - */ - public static void clearPref(String name) - { - allPrefsMap.remove(name); - } - - /** - * Look up a PrefInt by name in the map of all Prefs. Return defaultValue if PrefInt's value is - * null. - * - * @param name - * Name of PrefInt - * @param defaultValue - * default value for PrefInt - * - * @return PrefInt's value or default value if doesn't exist - */ - public static int lookupInt(String name, int defaultValue) throws ClassCastException - { - /* - * could do this -- its heavier weight -- create a Pref if there wasn't one, and set its default - * value as here PrefInt prefInt = usePrefInt(name, defaultValue); return prefInt.value(); - */ - PrefInt prefInt = ((PrefInt) lookupPref(name)); - - return (prefInt == null) ? defaultValue : prefInt.value(); - } - - /** - * Look up a PrefInt by name in the map of all Prefs. - * - * @param name - * Name of PrefInt - * - * @return PrefInt's value or 0 - */ - public static int lookupInt(String name) throws ClassCastException - { - return lookupInt(name, 0); - } - - /** - * Look up a PrefLong by name in the map of all Prefs. Return defaultValue if PrefInt's value is - * null. - * - * @param name - * Name of PrefLong - * @param defaultValue - * default value for PrefLong - * - * @return PrefInt's value or default value if doesn't exist - */ - public static long lookupLong(String name, long defaultValue) throws ClassCastException - { - PrefLong prefLong = ((PrefLong) lookupPref(name)); - - return (prefLong == null) ? defaultValue : prefLong.value(); - } - - /** - * Look up a PrefLong by name in the map of all Prefs. - * - * @param name - * Name of PrefLong - * - * @return PrefInt's value or 0 - */ - public static long lookupLong(String name) throws ClassCastException - { - return lookupInt(name, 0); - } - - /** - * Look up a PrefBoolean by name in the map of all Prefs. Return defaultValue if PrefBoolean's - * value is null. - * - * @param name - * Name of PrefBoolean - * @param defaultValue - * default value for PrefBoolean - * - * @return PrefBoolean's value or default value if doesn't exist - */ - public static boolean lookupBoolean(String name, boolean defaultValue) throws ClassCastException - { - PrefBoolean prefBoolean = ((PrefBoolean) lookupPref(name)); - return (prefBoolean == null) ? defaultValue : prefBoolean.value(); - } - - /** - * Look up a PrefBoolean by name in the map of all Prefs. - * - * @param name - * Name of PrefBoolean - * - * @return PrefBoolean's value or false if doesn't exist - */ - public static boolean lookupBoolean(String name) throws ClassCastException - { - return lookupBoolean(name, false); - } - - /** - * Look up a PrefFloat by name in the map of all Prefs. Return defaultValue if PrefFloat's value - * is null. - * - * @param name - * Name of PrefFloat - * @param defaultValue - * default value to set PrefFloat to - * - * @return PrefFloat's value or default value if doesn't exist - */ - public static float lookupFloat(String name, float defaultValue) throws ClassCastException - { - PrefFloat prefFloat = ((PrefFloat) lookupPref(name)); - return (prefFloat == null) ? defaultValue : prefFloat.value(); - } - - /** - * Look up a PrefFloat by name in the map of all Prefs. - * - * @param name - * Name of PrefFloat - * - * @return PrefFloat's value (if exists) or 1.0f - */ - public static float lookupFloat(String name) throws ClassCastException - { - return lookupFloat(name, 1.0f); - } - - /** - * Look up a PrefDouble by name in the map of all Prefs. Return defaultValue if PrefDouble's value - * is null. - * - * @param name - * Name of PrefDouble - * @param defaultValue - * default value to set PrefDouble to - * - * @return PrefDouble's value or default value if doesn't exist - */ - public static double lookupDouble(String name, double defaultValue) throws ClassCastException - { - PrefDouble prefDouble = ((PrefDouble) lookupPref(name)); - return (prefDouble == null) ? defaultValue : prefDouble.value(); - } - - /** - * Look up a PrefDouble by name in the map of all Prefs. - * - * @param name - * Name of PrefDouble - * - * @return PrefDouble's value (if exists) or 1.0 - */ - public static double lookupDouble(String name) throws ClassCastException - { - return lookupDouble(name, 1.0); - } - - /** - * Look up a PrefString by name in the map of all Prefs. Return defaultValue if PrefString's value - * is null. - * - * @param name - * Name of PrefString - * @param defaultValue - * default value for PrefString - * - * @return PrefString's value or default value if doesn't exist - */ - public static String lookupString(String name, String defaultValue) throws ClassCastException - { - PrefString prefString = ((PrefString) lookupPref(name)); - return (prefString == null) ? defaultValue : prefString.value(); - } - - /** - * Look up a PrefString by name in the map of all Prefs. Return null if PrefString's value is - * null. - * - * @param name - * Name of PrefString - * - * @return PrefString's value or null - */ - public static String lookupString(String name) throws ClassCastException - { - return lookupString(name, null); - } - - /** - * Look up a PrefFile by name in the map of all Prefs. Return null if the PrefFile's value is - * null; - * - * @param name - * Name of the PrefFile - * @return PrefFile's value or null, if the Pref associated with name does not exist - * @throws ClassCastException - * if name does not match a PrefFile object - */ - public static File lookupFile(String name) throws ClassCastException - { - PrefFile prefFile = ((PrefFile) lookupPref(name)); - return (prefFile == null) ? null : prefFile.value(); - } - - /** - * Look up a PrefColor by name in the map of all Prefs. Return defaultValue if PrefColor's value - * is null. - * - * @param name - * Name of PrefColor - * @param defaultValue - * default value for PrefColor - * - * @return PrefColor's value or default value if doesn't exist - */ - public static Object lookupColor(String name, Object defaultValue) - { - return FundamentalPlatformSpecifics.get().lookupColor(name, defaultValue); - } - - /** - * Look up a PrefColor by name in the map of all Prefs. - * - * @param name - * Name of PrefColor - * - * @return PrefColor's value or null - */ - public static Object lookupColor(String name) throws ClassCastException - { - return lookupColor(name, null); - } - - /** - * Look up a PrefElementState by name in the map of all Prefs. Set to defaultValue if - * PrefElementState's value is null. - * - * @param name - * Name of PrefElementState - * - * @return PrefElementState's value or null if doesn't exist - */ - public static ElementState lookupElementState(String name) throws ClassCastException - { - PrefElementState prefElementState = ((PrefElementState) lookupPref(name)); - return (ElementState) ((prefElementState == null) ? null : prefElementState.value()); - } - - public static Enum lookupEnum(String name, Enum defaultValue) throws ClassCastException - { - PrefEnum prefEnum = ((PrefEnum) lookupPref(name)); - return (prefEnum == null) ? defaultValue : prefEnum.value(); - } - - /** - * Check for existence / membership. - * - * @param key - * - * @return true if there is a Pref already registered with name key - */ - public static boolean hasPref(String name) - { - return allPrefsMap.containsKey(name); - } - - /** - * Create an entry for this in the allPrefsMap. - * - */ - void register() - { - allPrefsMap.put(this.name, this); - } - - /** - * Check for existence / membership. - * - * @param key - * - * @return true if there is a Pref already registered with name key - */ - public static boolean containsKey(String key) - { - return allPrefsMap.containsKey(key); - } - - public String getName() - { - return name; - } - - public static void addPrefChangedListener(PrefChangedListener l) - { - listeners.add(l); - } - - private static void firePrefChangedEvent(Pref pref) - { - for (PrefChangedListener l : listeners) - { - l.prefChanged(pref); - } - } - - public static void prefUpdated(Pref pref) - { - firePrefChangedEvent(pref); - } - - /** - * @see ecologylab.serialization.types.element.IMappable#key() - */ - @Override - public String key() - { - return name; - } - - /** - * @see ecologylab.serialization.types.element.ArrayListState#clone() This clone method is - * REQUIRED for preferences being maintained by a servlet. The specific case that we have in - * place (dec '09) that uses this is the Studies framework. The clone functionality enables - * maintaining a preference set for each user in a user study. - */ - @Override - public abstract Pref clone(); - - /** - * This method can be called after the pref has translated, with the current session scope. - * - * @param scope - */ - public void postLoadHook(Scope scope) - { - - } - - @Override - public void deserializationPostHook(TranslationContext translationContext, Object object) - { - if (object instanceof Pref) - { - Pref pref = (Pref) object; - pref.register(); - } - } -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +//import java.awt.Color; +import java.io.File; +import java.util.LinkedList; + +import ecologylab.appframework.SingletonApplicationEnvironment; +import ecologylab.collections.Scope; +import ecologylab.platformspecifics.FundamentalPlatformSpecifics; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.element.IMappable; + +/** + * Generic base class for application Preference objects. + * + * @author andruid + */ + +@simpl_inherit +public abstract class Pref extends ElementState implements IMappable, Cloneable +{ + /** The global registry of Pref objects. Used for providing lookup services. */ + static final Scope> allPrefsMap = new Scope>(); + + /** The ApplicationEnvironment associated with this JVM. */ + static final SingletonApplicationEnvironment aE = null; + + /** Name of a Pref; provides index into the preferences map. */ + @simpl_scalar + protected String name; + + /** Cached value */ + T valueCached; + + /** + * The list of PrefChangedListeners registered to respond to changes in Prefs. + */ + static LinkedList listeners = new LinkedList(); + + /** No-argument constructor for XML translation. */ + public Pref() + { + super(); + } + + protected Pref(String name) + { + this.name = name; + } + + /** + * Public generic accessor for the value. Caches autoboxed values, for efficiency. + * + * @return + */ + public T value() + { + T result = valueCached; + if (result == null) + { + result = getValue(); + valueCached = result; + } + return result; + } + + /** + * Print Pref name and value + */ + public void print() + { + println("Pref: name: " + name + ", value: " + this.getValue()); + } + + /** + * Return String of Pref name and value + * + * @return String of Pref name and value + */ + @Override + public String toString() + { + return "Pref: " + name + "(" + this.getValue() + ")"; + } + + /** + * Generic get value returns the value as the actual type you want. This version should only be + * called by value(), so that autoboxed types can be cached. This method *does not* do the + * caching. + * + * @return + */ + protected abstract T getValue(); + + /** + * Generic value setter. Uses boxed reference objects for primitives, which are a bit extra + * expensive. + * + * @param newValue + */ + public abstract void setValue(T newValue); + + /** + * Performs all housekeeping associated with updating this Pref. prefUpdated() should be called + * whenever the value of this has been changed. + * + * Notifies all listeners that the pref's value has changed. + * + * Set valueCached to null + */ + protected void prefChanged() + { + valueCached = null; + + Pref.firePrefChangedEvent(this); + } + + /** + * This is for working with Prefs whose values you will continue to access as they + * are edited, live, by the user. The result will be immediate changes in the program's behavior. + *

+ * Lookup a Pref associated with name. If you find it return it. If not, create a new Pref object + * of the correct type. Set its value to default value. + * + * @param name + * Name of the Pref to lookup and find or create. + * @param defaultValue + * Initial value of the Pref if it didn't already exist. + * + * @return A usable Pref object associated with name, either from the registry or newly created + */ + public static PrefBoolean usePrefBoolean(String name, boolean defaultValue) + { + PrefBoolean pref = (PrefBoolean) lookupPref(name); + if (pref == null) + { + pref = new PrefBoolean(defaultValue); + pref.name = name; + pref.register(); + } + return pref; + } + + /** + * This is for working with Prefs whose values you will continue to access as they + * are edited, live, by the user. The result will be immediate changes in the program's behavior. + *

+ * Lookup a Pref associated with name. If you find it return it. If not, create a new Pref object + * of the correct type. Set its value to default value. + * + * @param name + * Name of the Pref to lookup and find or create. + * @param defaultValue + * Initial value of the Pref if it didn't already exist. + * + * @return A usable Pref object associated with name, either from the registry or newly created + */ + public static PrefFloat usePrefFloat(String name, float defaultValue) + { + PrefFloat pref = (PrefFloat) lookupPref(name); + if (pref == null) + { + pref = new PrefFloat(defaultValue); + pref.name = name; + pref.register(); + } + return pref; + } + + /** + * This is for working with Prefs whose values you will continue to access as they + * are edited, live, by the user. The result will be immediate changes in the program's behavior. + *

+ * Lookup a Pref associated with name. If you find it return it. If not, create a new Pref object + * of the correct type. Set its value to default value. + * + * @param name + * Name of the Pref to lookup and find or create. + * @param defaultValue + * Initial value of the Pref if it didn't already exist. + * + * @return A usable Pref object associated with name, either from the registry or newly created + */ + public static PrefString usePrefString(String name, String defaultValue) + { + PrefString pref = (PrefString) lookupPref(name); + if (pref == null) + { + pref = new PrefString(defaultValue); + pref.name = name; + pref.register(); + } + return pref; + } + + /** + * This is for working with Prefs whose values you will continue to access as they + * are edited, live, by the user. The result will be immediate changes in the program's behavior. + *

+ * Lookup a Pref associated with name. If you find it return it. If not, create a new Pref object + * of the correct type. Set its value to default value. + * + * @param name + * Name of the Pref to lookup and find or create. + * @param defaultValue + * Initial value of the Pref if it didn't already exist. + * + * @return A usable Pref object associated with name, either from the registry or newly created + */ + public static PrefInt usePrefInt(String name, int defaultValue) + { + PrefInt pref = (PrefInt) lookupPref(name); + if (pref == null) + { + pref = new PrefInt(defaultValue); + pref.name = name; + pref.register(); + } + return pref; + } + + /** + * Lookup a Pref associated with name. If you find it, it is the operative Pref If not, create a + * new Pref object of the correct type, and register it. + *

+ * Set the value of the operative Pref to that passed in here. + * + * @param name + * Name of the Pref to lookup and find or create. + * @param defaultValue + * Initial value of the Pref if it didn't already exist. + */ + public static void useAndSetPrefInt(String name, int value) + { + PrefInt thatPrefInt = usePrefInt(name, value); + thatPrefInt.setValue(value); + } + + public static void useAndSetPrefEnum(String name, Enum value) + { + PrefEnum thatPrefEnum = usePrefEnum(name, value); + thatPrefEnum.setValue(value); + } + + /** + * This is for working with Prefs whose values you will continue to access as they + * are edited, live, by the user. The result will be immediate changes in the program's behavior. + *

+ * Lookup a Pref associated with name. If you find it return it. If not, create a new Pref object + * of the correct type. Set its value to default value. + * + * @param name + * Name of the Pref to lookup and find or create. + * @param defaultValue + * Initial value of the Pref if it didn't already exist. + * + * @return A usable Pref object associated with name, either from the registry or newly created + */ + public static Object usePrefColor(String name, Object defaultValue) + { + return FundamentalPlatformSpecifics.get().usePrefColor(name, defaultValue); + } + + /** + * This is for working with Prefs whose values you will continue to access as they + * are edited, live, by the user. The result will be immediate changes in the program's behavior. + *

+ * Lookup a Pref associated with name. If you find it return it. If not, create a new Pref object + * of the correct type. Set its value to default value. + * + * @param name + * Name of the Pref to lookup and find or create. + * @param defaultValue + * Initial value of the Pref if it didn't already exist. + * + * @return A usable Pref object associated with name, either from the registry or newly created + */ + public static PrefEnum usePrefEnum(String name, Enum defaultValue) + { + PrefEnum pref = (PrefEnum) lookupPref(name); + if (pref == null) + { + pref = new PrefEnum(defaultValue); + pref.name = name; + pref.register(); + } + return pref; + } + + /** + * Look up a Pref by name in the map of all Prefs + * + * @param name + * Name of Pref + * + * @return Pref with the given name + */ + public static Pref lookupPref(String name) + { + Pref pref = allPrefsMap.get(name); + return pref; + } + + public static void printAllPrefsMap() + { + for (Pref p : allPrefsMap.values()) + { + System.out.println("PREF: " + p.getName() + " = " + p.value()); + } + } + + /** + * Turn the entry for a pref name to null in the global map. + * + * @param name + */ + public static void clearPref(String name) + { + allPrefsMap.remove(name); + } + + /** + * Look up a PrefInt by name in the map of all Prefs. Return defaultValue if PrefInt's value is + * null. + * + * @param name + * Name of PrefInt + * @param defaultValue + * default value for PrefInt + * + * @return PrefInt's value or default value if doesn't exist + */ + public static int lookupInt(String name, int defaultValue) throws ClassCastException + { + /* + * could do this -- its heavier weight -- create a Pref if there wasn't one, and set its default + * value as here PrefInt prefInt = usePrefInt(name, defaultValue); return prefInt.value(); + */ + PrefInt prefInt = ((PrefInt) lookupPref(name)); + + return (prefInt == null) ? defaultValue : prefInt.value(); + } + + /** + * Look up a PrefInt by name in the map of all Prefs. + * + * @param name + * Name of PrefInt + * + * @return PrefInt's value or 0 + */ + public static int lookupInt(String name) throws ClassCastException + { + return lookupInt(name, 0); + } + + /** + * Look up a PrefLong by name in the map of all Prefs. Return defaultValue if PrefInt's value is + * null. + * + * @param name + * Name of PrefLong + * @param defaultValue + * default value for PrefLong + * + * @return PrefInt's value or default value if doesn't exist + */ + public static long lookupLong(String name, long defaultValue) throws ClassCastException + { + PrefLong prefLong = ((PrefLong) lookupPref(name)); + + return (prefLong == null) ? defaultValue : prefLong.value(); + } + + /** + * Look up a PrefLong by name in the map of all Prefs. + * + * @param name + * Name of PrefLong + * + * @return PrefInt's value or 0 + */ + public static long lookupLong(String name) throws ClassCastException + { + return lookupInt(name, 0); + } + + /** + * Look up a PrefBoolean by name in the map of all Prefs. Return defaultValue if PrefBoolean's + * value is null. + * + * @param name + * Name of PrefBoolean + * @param defaultValue + * default value for PrefBoolean + * + * @return PrefBoolean's value or default value if doesn't exist + */ + public static boolean lookupBoolean(String name, boolean defaultValue) throws ClassCastException + { + PrefBoolean prefBoolean = ((PrefBoolean) lookupPref(name)); + return (prefBoolean == null) ? defaultValue : prefBoolean.value(); + } + + /** + * Look up a PrefBoolean by name in the map of all Prefs. + * + * @param name + * Name of PrefBoolean + * + * @return PrefBoolean's value or false if doesn't exist + */ + public static boolean lookupBoolean(String name) throws ClassCastException + { + return lookupBoolean(name, false); + } + + /** + * Look up a PrefFloat by name in the map of all Prefs. Return defaultValue if PrefFloat's value + * is null. + * + * @param name + * Name of PrefFloat + * @param defaultValue + * default value to set PrefFloat to + * + * @return PrefFloat's value or default value if doesn't exist + */ + public static float lookupFloat(String name, float defaultValue) throws ClassCastException + { + PrefFloat prefFloat = ((PrefFloat) lookupPref(name)); + return (prefFloat == null) ? defaultValue : prefFloat.value(); + } + + /** + * Look up a PrefFloat by name in the map of all Prefs. + * + * @param name + * Name of PrefFloat + * + * @return PrefFloat's value (if exists) or 1.0f + */ + public static float lookupFloat(String name) throws ClassCastException + { + return lookupFloat(name, 1.0f); + } + + /** + * Look up a PrefDouble by name in the map of all Prefs. Return defaultValue if PrefDouble's value + * is null. + * + * @param name + * Name of PrefDouble + * @param defaultValue + * default value to set PrefDouble to + * + * @return PrefDouble's value or default value if doesn't exist + */ + public static double lookupDouble(String name, double defaultValue) throws ClassCastException + { + PrefDouble prefDouble = ((PrefDouble) lookupPref(name)); + return (prefDouble == null) ? defaultValue : prefDouble.value(); + } + + /** + * Look up a PrefDouble by name in the map of all Prefs. + * + * @param name + * Name of PrefDouble + * + * @return PrefDouble's value (if exists) or 1.0 + */ + public static double lookupDouble(String name) throws ClassCastException + { + return lookupDouble(name, 1.0); + } + + /** + * Look up a PrefString by name in the map of all Prefs. Return defaultValue if PrefString's value + * is null. + * + * @param name + * Name of PrefString + * @param defaultValue + * default value for PrefString + * + * @return PrefString's value or default value if doesn't exist + */ + public static String lookupString(String name, String defaultValue) throws ClassCastException + { + PrefString prefString = ((PrefString) lookupPref(name)); + return (prefString == null) ? defaultValue : prefString.value(); + } + + /** + * Look up a PrefString by name in the map of all Prefs. Return null if PrefString's value is + * null. + * + * @param name + * Name of PrefString + * + * @return PrefString's value or null + */ + public static String lookupString(String name) throws ClassCastException + { + return lookupString(name, null); + } + + /** + * Look up a PrefFile by name in the map of all Prefs. Return null if the PrefFile's value is + * null; + * + * @param name + * Name of the PrefFile + * @return PrefFile's value or null, if the Pref associated with name does not exist + * @throws ClassCastException + * if name does not match a PrefFile object + */ + public static File lookupFile(String name) throws ClassCastException + { + PrefFile prefFile = ((PrefFile) lookupPref(name)); + return (prefFile == null) ? null : prefFile.value(); + } + + /** + * Look up a PrefColor by name in the map of all Prefs. Return defaultValue if PrefColor's value + * is null. + * + * @param name + * Name of PrefColor + * @param defaultValue + * default value for PrefColor + * + * @return PrefColor's value or default value if doesn't exist + */ + public static Object lookupColor(String name, Object defaultValue) + { + return FundamentalPlatformSpecifics.get().lookupColor(name, defaultValue); + } + + /** + * Look up a PrefColor by name in the map of all Prefs. + * + * @param name + * Name of PrefColor + * + * @return PrefColor's value or null + */ + public static Object lookupColor(String name) throws ClassCastException + { + return lookupColor(name, null); + } + + /** + * Look up a PrefElementState by name in the map of all Prefs. Set to defaultValue if + * PrefElementState's value is null. + * + * @param name + * Name of PrefElementState + * + * @return PrefElementState's value or null if doesn't exist + */ + public static ElementState lookupElementState(String name) throws ClassCastException + { + PrefElementState prefElementState = ((PrefElementState) lookupPref(name)); + return (ElementState) ((prefElementState == null) ? null : prefElementState.value()); + } + + public static Enum lookupEnum(String name, Enum defaultValue) throws ClassCastException + { + PrefEnum prefEnum = ((PrefEnum) lookupPref(name)); + return (prefEnum == null) ? defaultValue : prefEnum.value(); + } + + /** + * Check for existence / membership. + * + * @param key + * + * @return true if there is a Pref already registered with name key + */ + public static boolean hasPref(String name) + { + return allPrefsMap.containsKey(name); + } + + /** + * Create an entry for this in the allPrefsMap. + * + */ + void register() + { + allPrefsMap.put(this.name, this); + } + + /** + * Check for existence / membership. + * + * @param key + * + * @return true if there is a Pref already registered with name key + */ + public static boolean containsKey(String key) + { + return allPrefsMap.containsKey(key); + } + + public String getName() + { + return name; + } + + public static void addPrefChangedListener(PrefChangedListener l) + { + listeners.add(l); + } + + private static void firePrefChangedEvent(Pref pref) + { + for (PrefChangedListener l : listeners) + { + l.prefChanged(pref); + } + } + + public static void prefUpdated(Pref pref) + { + firePrefChangedEvent(pref); + } + + /** + * @see ecologylab.serialization.types.element.IMappable#key() + */ + @Override + public String key() + { + return name; + } + + /** + * @see ecologylab.serialization.types.element.ArrayListState#clone() This clone method is + * REQUIRED for preferences being maintained by a servlet. The specific case that we have in + * place (dec '09) that uses this is the Studies framework. The clone functionality enables + * maintaining a preference set for each user in a user study. + */ + @Override + public abstract Pref clone(); + + /** + * This method can be called after the pref has translated, with the current session scope. + * + * @param scope + */ + public void postLoadHook(Scope scope) + { + + } + + @Override + public void deserializationPostHook(TranslationContext translationContext, Object object) + { + if (object instanceof Pref) + { + Pref pref = (Pref) object; + pref.register(); + } + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefBoolean.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefBoolean.java index 36541c04..56582d25 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefBoolean.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefBoolean.java @@ -1,94 +1,94 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Pref for a Boolean - * - * @author andruid - * - */ - -@simpl_inherit -public class PrefBoolean extends Pref -{ - /** - * Value of Pref - */ - @simpl_scalar - boolean value; - - /** - * - */ - public PrefBoolean() - { - super(); - } - - /** - * Instantiate Pref to value - * - * @param value - */ - public PrefBoolean(boolean value) - { - super(); - this.value = value; - } - - public PrefBoolean(String name, boolean value) - { - super(name); - this.value = value; - } - - /** - * Get the value of the Pref - * - * @return The value of the Pref - */ - @Override - protected Boolean getValue() - { - return value; - } - - /** - * Set the value of the Pref given a Boolean (big B) - * - * @param The - * Boolean value the Pref will be set to - */ - @Override - public void setValue(Boolean newValue) - { - setValue(newValue.booleanValue()); - } - - /** - * Set the value of the Pref given a boolean (small b) - * - * @param The - * boolean value the Pref will be set to - */ - public void setValue(boolean value) - { - this.value = value; - - prefChanged(); - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#clone() - */ - @Override - public Pref clone() - { - return new PrefBoolean(this.name, this.value); - } -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Pref for a Boolean + * + * @author andruid + * + */ + +@simpl_inherit +public class PrefBoolean extends Pref +{ + /** + * Value of Pref + */ + @simpl_scalar + boolean value; + + /** + * + */ + public PrefBoolean() + { + super(); + } + + /** + * Instantiate Pref to value + * + * @param value + */ + public PrefBoolean(boolean value) + { + super(); + this.value = value; + } + + public PrefBoolean(String name, boolean value) + { + super(name); + this.value = value; + } + + /** + * Get the value of the Pref + * + * @return The value of the Pref + */ + @Override + protected Boolean getValue() + { + return value; + } + + /** + * Set the value of the Pref given a Boolean (big B) + * + * @param The + * Boolean value the Pref will be set to + */ + @Override + public void setValue(Boolean newValue) + { + setValue(newValue.booleanValue()); + } + + /** + * Set the value of the Pref given a boolean (small b) + * + * @param The + * boolean value the Pref will be set to + */ + public void setValue(boolean value) + { + this.value = value; + + prefChanged(); + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#clone() + */ + @Override + public Pref clone() + { + return new PrefBoolean(this.name, this.value); + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefChangedListener.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefChangedListener.java index 46331bf2..3417db14 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefChangedListener.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefChangedListener.java @@ -1,24 +1,24 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -/** - * An object that monitors a Pref or set of Prefs to respond to changes in - * it/them. - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public interface PrefChangedListener -{ - /** - * Responds to a change in a Pref object. This method will be called - * whenever ANY Pref changes, so the Object implementing this interface must - * decide what to do with the Pref, most likely based upon its getName() - * method. - * - * @param pref - */ - public void prefChanged(Pref pref); -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +/** + * An object that monitors a Pref or set of Prefs to respond to changes in + * it/them. + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public interface PrefChangedListener +{ + /** + * Responds to a change in a Pref object. This method will be called + * whenever ANY Pref changes, so the Object implementing this interface must + * decide what to do with the Pref, most likely based upon its getName() + * method. + * + * @param pref + */ + public void prefChanged(Pref pref); +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefElementState.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefElementState.java index 6acf1e6d..42c50051 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefElementState.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefElementState.java @@ -1,67 +1,67 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.ElementState; - -/** - * A preference that is an ElementState. - * - * @author andruid - */ -public class PrefElementState extends Pref -{ - - T elementStatePref; - - /** - * - */ - public PrefElementState() - { - super(); - } - - public PrefElementState(String name) - { - super(); - this.name = name; - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#getValue() - */ - @Override - protected T getValue() - { - return elementStatePref; - } - - /* - * (non-Javadoc) - * - * @see ecologylab.appframework.types.prefs.Pref#setValue(T) - */ - @Override - public void setValue(T newValue) - { - elementStatePref = newValue; - prefChanged(); - } - - /** - * XXX NOTE: THIS IS AN UNSAFE CLONE. IF THE VALUE OF THIS PREFERENCE IS TO BE MODIFIED, THIS - * METHOD MUST BE RECONSIDERED. A very cool and proper way to do this would be to translate value - * to and from XML, but this is impossible without the correct translation scope. - * - * @see ecologylab.appframework.types.prefs.Pref#clone() - */ - @Override - public PrefElementState clone() - { - PrefElementState pES = new PrefElementState(this.name); - - return pES; - } -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.ElementState; + +/** + * A preference that is an ElementState. + * + * @author andruid + */ +public class PrefElementState extends Pref +{ + + T elementStatePref; + + /** + * + */ + public PrefElementState() + { + super(); + } + + public PrefElementState(String name) + { + super(); + this.name = name; + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#getValue() + */ + @Override + protected T getValue() + { + return elementStatePref; + } + + /* + * (non-Javadoc) + * + * @see ecologylab.appframework.types.prefs.Pref#setValue(T) + */ + @Override + public void setValue(T newValue) + { + elementStatePref = newValue; + prefChanged(); + } + + /** + * XXX NOTE: THIS IS AN UNSAFE CLONE. IF THE VALUE OF THIS PREFERENCE IS TO BE MODIFIED, THIS + * METHOD MUST BE RECONSIDERED. A very cool and proper way to do this would be to translate value + * to and from XML, but this is impossible without the correct translation scope. + * + * @see ecologylab.appframework.types.prefs.Pref#clone() + */ + @Override + public PrefElementState clone() + { + PrefElementState pES = new PrefElementState(this.name); + + return pES; + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefFile.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefFile.java index b42b2e17..179f5477 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefFile.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefFile.java @@ -1,146 +1,146 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import java.io.File; - -import ecologylab.appframework.EnvironmentGeneric; -import ecologylab.appframework.PropertiesAndDirectories; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Pref indicating a File. Stores a value that indicates either an absolute path, or one relative to - * the code base or application data dir for the application using the Pref. - * - * @author ross - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -@simpl_inherit -public class PrefFile extends Pref -{ - /** Path associated with this preference. */ - @simpl_scalar - String value; - - /** - * Context indicating the type of path specified by value. Possible values are ABSOLUTE_PATH, - * CODE_BASE, or APP_DATA_DIR. - */ - @simpl_scalar - int pathContext = ABSOLUTE_PATH; - - /** Indicates that value is an absolute path. */ - public static final int ABSOLUTE_PATH = 0; - - /** - * Indicates that value is a path relative to the codebase of the application using this Pref. - */ - public static final int CODE_BASE = 1; - - /** - * Indicates that value is a path relative to the data directory associated with the application - * using this Pref. - */ - public static final int APP_DATA_DIR = 2; - - /** - * The cached File object that goes with this Pref; lazilly evaluated. fileValue should NEVER be - * directly referenced, it should only be accessed through the file() method. - */ - File fileValue = null; - - /** No-argument constructor for XML translation. */ - public PrefFile() - { - super(); - } - - public PrefFile(String name, String value, int pathContext) - { - this.name = name; - this.value = value; - this.pathContext = pathContext; - } - - /** - * Instantiate Pref to value - * - * @param value - */ - public PrefFile(File value) - { - super(); - this.setValue(value); - } - - /** - * Get the value of the Pref. If this's file path includes '$FIND_PATH', then this builds a file - * based upon the pathname provided by the App Framework. - * - * @return The value of the Pref - */ - @Override - protected File getValue() - { - return file(); - } - - /** - * Sets up this Pref object to be associated with newValue as an absolute path. - * - * @see ecologylab.appframework.types.prefs.Pref#setValue(java.lang.Object) - */ - @Override - public void setValue(File newValue) - { - this.value = newValue.getAbsolutePath(); - - this.prefChanged(); - } - - /** - * Sets up this Pref object to be associated with newValue as a path indicated by pathContext. - * - * @param newValue - * @param pathContext - */ - public void setValue(String newValue, int pathContext) - { - this.value = newValue; - this.pathContext = pathContext; - - this.prefChanged(); - } - - private final File file() - { - if (fileValue == null) - { - switch (pathContext) - { - case (CODE_BASE): - this.fileValue = new File(EnvironmentGeneric.codeBase().file(), value); - break; - case (APP_DATA_DIR): - this.fileValue = new File(PropertiesAndDirectories.applicationDataDir(), value); - break; - default: - this.fileValue = new File(value); - } - } - - return fileValue; - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#clone() - */ - @Override - public Pref clone() - { - return new PrefFile(this.name, this.value, this.pathContext); - } -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import java.io.File; + +import ecologylab.appframework.EnvironmentGeneric; +import ecologylab.appframework.PropertiesAndDirectories; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Pref indicating a File. Stores a value that indicates either an absolute path, or one relative to + * the code base or application data dir for the application using the Pref. + * + * @author ross + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +@simpl_inherit +public class PrefFile extends Pref +{ + /** Path associated with this preference. */ + @simpl_scalar + String value; + + /** + * Context indicating the type of path specified by value. Possible values are ABSOLUTE_PATH, + * CODE_BASE, or APP_DATA_DIR. + */ + @simpl_scalar + int pathContext = ABSOLUTE_PATH; + + /** Indicates that value is an absolute path. */ + public static final int ABSOLUTE_PATH = 0; + + /** + * Indicates that value is a path relative to the codebase of the application using this Pref. + */ + public static final int CODE_BASE = 1; + + /** + * Indicates that value is a path relative to the data directory associated with the application + * using this Pref. + */ + public static final int APP_DATA_DIR = 2; + + /** + * The cached File object that goes with this Pref; lazilly evaluated. fileValue should NEVER be + * directly referenced, it should only be accessed through the file() method. + */ + File fileValue = null; + + /** No-argument constructor for XML translation. */ + public PrefFile() + { + super(); + } + + public PrefFile(String name, String value, int pathContext) + { + this.name = name; + this.value = value; + this.pathContext = pathContext; + } + + /** + * Instantiate Pref to value + * + * @param value + */ + public PrefFile(File value) + { + super(); + this.setValue(value); + } + + /** + * Get the value of the Pref. If this's file path includes '$FIND_PATH', then this builds a file + * based upon the pathname provided by the App Framework. + * + * @return The value of the Pref + */ + @Override + protected File getValue() + { + return file(); + } + + /** + * Sets up this Pref object to be associated with newValue as an absolute path. + * + * @see ecologylab.appframework.types.prefs.Pref#setValue(java.lang.Object) + */ + @Override + public void setValue(File newValue) + { + this.value = newValue.getAbsolutePath(); + + this.prefChanged(); + } + + /** + * Sets up this Pref object to be associated with newValue as a path indicated by pathContext. + * + * @param newValue + * @param pathContext + */ + public void setValue(String newValue, int pathContext) + { + this.value = newValue; + this.pathContext = pathContext; + + this.prefChanged(); + } + + private final File file() + { + if (fileValue == null) + { + switch (pathContext) + { + case (CODE_BASE): + this.fileValue = new File(EnvironmentGeneric.codeBase().file(), value); + break; + case (APP_DATA_DIR): + this.fileValue = new File(PropertiesAndDirectories.applicationDataDir(), value); + break; + default: + this.fileValue = new File(value); + } + } + + return fileValue; + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#clone() + */ + @Override + public Pref clone() + { + return new PrefFile(this.name, this.value, this.pathContext); + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefFloat.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefFloat.java index 8a8af8ca..c47a4dd3 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefFloat.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefFloat.java @@ -1,95 +1,95 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Pref for a Float - * - * @author andruid - * - */ - -@simpl_inherit -public class PrefFloat extends Pref -{ - /** - * Value of Pref - */ - @simpl_scalar - float value; - - /** - * - */ - public PrefFloat() - { - super(); - } - - /** - * Instantiate Pref to value - * - * @param value - */ - public PrefFloat(float value) - { - super(); - this.value = value; - } - - public PrefFloat(String name, float value) - { - super(); - this.name = name; - this.value = value; - } - - /** - * Get the value of the Pref - * - * @return The value of the Pref - */ - @Override - protected Float getValue() - { - return value; - } - - /** - * Set the value of the Pref given a Float (big F) - * - * @param The - * Float value the Pref will be set to - */ - @Override - public void setValue(Float newValue) - { - setValue(newValue.floatValue()); - } - - /** - * Set the value of the Pref given a float (small f) - * - * @param The - * float value the Pref will be set to - */ - public void setValue(float value) - { - this.value = value; - - prefChanged(); - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#clone() - */ - @Override - public Pref clone() - { - return new PrefFloat(this.name, this.value); - } -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Pref for a Float + * + * @author andruid + * + */ + +@simpl_inherit +public class PrefFloat extends Pref +{ + /** + * Value of Pref + */ + @simpl_scalar + float value; + + /** + * + */ + public PrefFloat() + { + super(); + } + + /** + * Instantiate Pref to value + * + * @param value + */ + public PrefFloat(float value) + { + super(); + this.value = value; + } + + public PrefFloat(String name, float value) + { + super(); + this.name = name; + this.value = value; + } + + /** + * Get the value of the Pref + * + * @return The value of the Pref + */ + @Override + protected Float getValue() + { + return value; + } + + /** + * Set the value of the Pref given a Float (big F) + * + * @param The + * Float value the Pref will be set to + */ + @Override + public void setValue(Float newValue) + { + setValue(newValue.floatValue()); + } + + /** + * Set the value of the Pref given a float (small f) + * + * @param The + * float value the Pref will be set to + */ + public void setValue(float value) + { + this.value = value; + + prefChanged(); + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#clone() + */ + @Override + public Pref clone() + { + return new PrefFloat(this.name, this.value); + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefInt.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefInt.java index fc4d1dd9..9df02cf0 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefInt.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefInt.java @@ -1,92 +1,92 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Pref for an Integer - * - * @author andruid - * - */ - -@simpl_inherit -public class PrefInt extends Pref -{ - /** - * Value of Pref - */ - @simpl_scalar - int value; - - /** - * - */ - public PrefInt() - { - super(); - } - - public PrefInt(String name, int value) - { - super(name); - - this.value = value; - } - - /** - * Instantiate Pref to value - * - * @param value - */ - public PrefInt(int value) - { - this(null, value); - } - - /** - * @return The - */ - @Override - protected Integer getValue() - { - return value; - } - - /** - * Set the value of the Pref given an Integer - * - * @param The - * Integer value the Pref will be set to - */ - @Override - public void setValue(Integer newValue) - { - setValue(newValue.intValue()); - } - - /** - * Set the value of the Pref given an int - * - * @param The - * int value the Pref will be set to - */ - public void setValue(int value) - { - this.value = value; - - prefChanged(); - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#clone() - */ - @Override - public Pref clone() - { - return new PrefInt(this.name, this.value); - } -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Pref for an Integer + * + * @author andruid + * + */ + +@simpl_inherit +public class PrefInt extends Pref +{ + /** + * Value of Pref + */ + @simpl_scalar + int value; + + /** + * + */ + public PrefInt() + { + super(); + } + + public PrefInt(String name, int value) + { + super(name); + + this.value = value; + } + + /** + * Instantiate Pref to value + * + * @param value + */ + public PrefInt(int value) + { + this(null, value); + } + + /** + * @return The + */ + @Override + protected Integer getValue() + { + return value; + } + + /** + * Set the value of the Pref given an Integer + * + * @param The + * Integer value the Pref will be set to + */ + @Override + public void setValue(Integer newValue) + { + setValue(newValue.intValue()); + } + + /** + * Set the value of the Pref given an int + * + * @param The + * int value the Pref will be set to + */ + public void setValue(int value) + { + this.value = value; + + prefChanged(); + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#clone() + */ + @Override + public Pref clone() + { + return new PrefInt(this.name, this.value); + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefLong.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefLong.java index 68afea15..f7168747 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefLong.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefLong.java @@ -1,90 +1,90 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Pref for a Long - * - * @author andruid, Zachary O. Toups (zach@ecologylab.net) - * - */ - -@simpl_inherit -public class PrefLong extends Pref -{ - /** Value of Pref */ - @simpl_scalar - long value; - - /** - * - */ - public PrefLong() - { - super(); - } - - public PrefLong(String name, long value) - { - super(name); - - this.value = value; - } - - /** - * Instantiate Pref to value - * - * @param value - */ - public PrefLong(long value) - { - this(null, value); - } - - /** - * @return The - */ - @Override - protected Long getValue() - { - return value; - } - - /** - * Set the value of the Pref given an Integer - * - * @param The - * Integer value the Pref will be set to - */ - @Override - public void setValue(Long newValue) - { - setValue(newValue.longValue()); - } - - /** - * Set the value of the Pref given an int - * - * @param The - * int value the Pref will be set to - */ - public void setValue(long value) - { - this.value = value; - - prefChanged(); - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#clone() - */ - @Override - public Pref clone() - { - return new PrefLong(this.name, this.value); - } -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Pref for a Long + * + * @author andruid, Zachary O. Toups (zach@ecologylab.net) + * + */ + +@simpl_inherit +public class PrefLong extends Pref +{ + /** Value of Pref */ + @simpl_scalar + long value; + + /** + * + */ + public PrefLong() + { + super(); + } + + public PrefLong(String name, long value) + { + super(name); + + this.value = value; + } + + /** + * Instantiate Pref to value + * + * @param value + */ + public PrefLong(long value) + { + this(null, value); + } + + /** + * @return The + */ + @Override + protected Long getValue() + { + return value; + } + + /** + * Set the value of the Pref given an Integer + * + * @param The + * Integer value the Pref will be set to + */ + @Override + public void setValue(Long newValue) + { + setValue(newValue.longValue()); + } + + /** + * Set the value of the Pref given an int + * + * @param The + * int value the Pref will be set to + */ + public void setValue(long value) + { + this.value = value; + + prefChanged(); + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#clone() + */ + @Override + public Pref clone() + { + return new PrefLong(this.name, this.value); + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefSet.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefSet.java index 91c5887b..d18f4a66 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefSet.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefSet.java @@ -1,245 +1,245 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Set; - -import ecologylab.appframework.ApplicationPropertyNames; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_map; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scope; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * A serial set of Pref objects. Used for reading and writing (load and save). The static - * allPrefsMap in Pref is used for lookup. - * - * @author Cae - * @author andruid - */ - -@simpl_inherit -public class PrefSet extends ElementState implements ApplicationPropertyNames, Cloneable -{ - public static final String PREFS_TRANSLATION_SCOPE = "PREFS_TRANSLATION_SCOPE"; - - @simpl_map - @simpl_nowrap - @simpl_scope(PREFS_TRANSLATION_SCOPE) - HashMap> preferences; - - /** No-argument constructor for XML translation. */ - public PrefSet() - { - } - - /** - * Register the Pref, as well as adding it to the super ArrayListState. - * - * @param pref - * @return - */ - public Pref add(Pref pref) - { - Pref result = null; - - if (pref != null) - { - constructPreferencesIfNeeded(); - - result = preferences.put(pref.key(), pref); - pref.register(); - } - - return result; - } - - public Pref addLocalOnly(Pref pref) - { - constructPreferencesIfNeeded(); - - Pref result = preferences.put(pref.key(), pref); - - return result; - } - - /** - * - */ - private void constructPreferencesIfNeeded() - { - if (preferences == null) - preferences = new HashMap>(); - } - - /** - * Perform custom processing on the newly created child node, just before it is added to this. - *

- * This is part of depth-first traversal during translateFromXML(). - *

- * Add the entry to the category map. - * - * @param child - */ - // TODO -- get rid of this when we make ArrayListState implement Collection!!! - // (cause then this.add() will get called!) - @Override - protected void createChildHook(ElementState child) - { - Pref pref = (Pref) child; - pref.register(); - } - - - - /** - * Read Pref declarations from a file or across the net. - * - * @param purl - * @param translationScope - * @return - * @throws SIMPLTranslationException - */ - public static PrefSet load(ParsedURL purl, SimplTypesScope translationScope) - throws SIMPLTranslationException - { - File file = purl.file(); - PrefSet pS = null; - if ((file != null) && file.exists()) - pS = (PrefSet) translationScope.deserialize(purl, Format.XML); - - return pS; - } - - /** - * Read Pref declarations from a file or across the net. - * - * @param prefXML - * - Preferences in an XML format; to be translated into a PrefSet. - * @param translationScope - * @return - * @throws SIMPLTranslationException - */ - public static PrefSet load(String filename, SimplTypesScope translationScope) - throws SIMPLTranslationException - { - PrefSet pS = (PrefSet) translationScope.deserialize(new File(filename), Format.XML); - - return pS; - } - - /** - * Read Pref declarations from a file or across the net. - * - * @param prefXML - * - Preferences in an XML format; to be translated into a PrefSet. - * @param translationScope - * @return - * @throws SIMPLTranslationException - */ - public static PrefSet loadFromCharSequence(String prefXML, SimplTypesScope translationScope) - throws SIMPLTranslationException - { - PrefSet pS = (PrefSet) translationScope.deserialize(prefXML, StringFormat.XML); - - return pS; - } - - /** - * Remove the Pref from this, and from the global set. - * - * @param key - * @return - */ - public Pref clearPref(String key) - { - Pref.clearPref(key); - return preferences == null ? null : preferences.remove(key); - } - - /** - * @see ecologylab.serialization.types.element.HashMapState#clone() - */ - @Override - public PrefSet clone() - { - PrefSet retVal = new PrefSet(); - - if (preferences != null) - { - for (Pref p : preferences.values()) - { - retVal.add(p.clone()); - } - } - return retVal; - } - - public static final Collection> EMPTY_ARRAY_LIST = new ArrayList>(0); - - public Collection> values() - { - return preferences == null ? EMPTY_ARRAY_LIST : preferences.values(); - } - - public void append(PrefSet jNLPPrefSet) - { - for (Pref pref : jNLPPrefSet.values()) - { - this.put(pref.key(), pref); - pref.register(); - } - } - - public Set keySet() - { - return preferences.keySet(); - } - - public Pref get(String k) - { - return (preferences == null) ? null : preferences.get(k); - } - - public void put(String k, Pref object) - { - constructPreferencesIfNeeded(); - - preferences.put(k, object); - } - - public boolean containsKey(String key) - { - return (preferences == null) ? false : preferences.containsKey(key); - - } - - /** - * Add another prefSet to this one. - * - * @param prefSet - */ - public void addPrefSet(PrefSet prefSet) - { - constructPreferencesIfNeeded(); - - for (Pref pref : prefSet.values()) - add(pref); - } - - public int size() - { - return (preferences != null) ? preferences.size() : 0; - } -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Set; + +import ecologylab.appframework.ApplicationPropertyNames; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_map; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scope; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * A serial set of Pref objects. Used for reading and writing (load and save). The static + * allPrefsMap in Pref is used for lookup. + * + * @author Cae + * @author andruid + */ + +@simpl_inherit +public class PrefSet extends ElementState implements ApplicationPropertyNames, Cloneable +{ + public static final String PREFS_TRANSLATION_SCOPE = "PREFS_TRANSLATION_SCOPE"; + + @simpl_map + @simpl_nowrap + @simpl_scope(PREFS_TRANSLATION_SCOPE) + HashMap> preferences; + + /** No-argument constructor for XML translation. */ + public PrefSet() + { + } + + /** + * Register the Pref, as well as adding it to the super ArrayListState. + * + * @param pref + * @return + */ + public Pref add(Pref pref) + { + Pref result = null; + + if (pref != null) + { + constructPreferencesIfNeeded(); + + result = preferences.put(pref.key(), pref); + pref.register(); + } + + return result; + } + + public Pref addLocalOnly(Pref pref) + { + constructPreferencesIfNeeded(); + + Pref result = preferences.put(pref.key(), pref); + + return result; + } + + /** + * + */ + private void constructPreferencesIfNeeded() + { + if (preferences == null) + preferences = new HashMap>(); + } + + /** + * Perform custom processing on the newly created child node, just before it is added to this. + *

+ * This is part of depth-first traversal during translateFromXML(). + *

+ * Add the entry to the category map. + * + * @param child + */ + // TODO -- get rid of this when we make ArrayListState implement Collection!!! + // (cause then this.add() will get called!) + @Override + protected void createChildHook(ElementState child) + { + Pref pref = (Pref) child; + pref.register(); + } + + + + /** + * Read Pref declarations from a file or across the net. + * + * @param purl + * @param translationScope + * @return + * @throws SIMPLTranslationException + */ + public static PrefSet load(ParsedURL purl, SimplTypesScope translationScope) + throws SIMPLTranslationException + { + File file = purl.file(); + PrefSet pS = null; + if ((file != null) && file.exists()) + pS = (PrefSet) translationScope.deserialize(purl, Format.XML); + + return pS; + } + + /** + * Read Pref declarations from a file or across the net. + * + * @param prefXML + * - Preferences in an XML format; to be translated into a PrefSet. + * @param translationScope + * @return + * @throws SIMPLTranslationException + */ + public static PrefSet load(String filename, SimplTypesScope translationScope) + throws SIMPLTranslationException + { + PrefSet pS = (PrefSet) translationScope.deserialize(new File(filename), Format.XML); + + return pS; + } + + /** + * Read Pref declarations from a file or across the net. + * + * @param prefXML + * - Preferences in an XML format; to be translated into a PrefSet. + * @param translationScope + * @return + * @throws SIMPLTranslationException + */ + public static PrefSet loadFromCharSequence(String prefXML, SimplTypesScope translationScope) + throws SIMPLTranslationException + { + PrefSet pS = (PrefSet) translationScope.deserialize(prefXML, StringFormat.XML); + + return pS; + } + + /** + * Remove the Pref from this, and from the global set. + * + * @param key + * @return + */ + public Pref clearPref(String key) + { + Pref.clearPref(key); + return preferences == null ? null : preferences.remove(key); + } + + /** + * @see ecologylab.serialization.types.element.HashMapState#clone() + */ + @Override + public PrefSet clone() + { + PrefSet retVal = new PrefSet(); + + if (preferences != null) + { + for (Pref p : preferences.values()) + { + retVal.add(p.clone()); + } + } + return retVal; + } + + public static final Collection> EMPTY_ARRAY_LIST = new ArrayList>(0); + + public Collection> values() + { + return preferences == null ? EMPTY_ARRAY_LIST : preferences.values(); + } + + public void append(PrefSet jNLPPrefSet) + { + for (Pref pref : jNLPPrefSet.values()) + { + this.put(pref.key(), pref); + pref.register(); + } + } + + public Set keySet() + { + return preferences.keySet(); + } + + public Pref get(String k) + { + return (preferences == null) ? null : preferences.get(k); + } + + public void put(String k, Pref object) + { + constructPreferencesIfNeeded(); + + preferences.put(k, object); + } + + public boolean containsKey(String key) + { + return (preferences == null) ? false : preferences.containsKey(key); + + } + + /** + * Add another prefSet to this one. + * + * @param prefSet + */ + public void addPrefSet(PrefSet prefSet) + { + constructPreferencesIfNeeded(); + + for (Pref pref : prefSet.values()) + add(pref); + } + + public int size() + { + return (preferences != null) ? preferences.size() : 0; + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefSetBaseClassProvider.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefSetBaseClassProvider.java index 81d6b613..3c494fa7 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefSetBaseClassProvider.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefSetBaseClassProvider.java @@ -1,40 +1,40 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.TranslationsClassProvider; - -/** - * Provides the list of Class'es used for translating the PrefSet class. This class is used to - * provide the base list of Class'es that will be provided to an ApplicationEnvironment. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class PrefSetBaseClassProvider extends TranslationsClassProvider -{ - public static final PrefSetBaseClassProvider STATIC_INSTANCE = new PrefSetBaseClassProvider(); - - protected PrefSetBaseClassProvider() - { - } - - /** - * @see ecologylab.serialization.TranslationsClassProvider#specificSuppliedClasses() - */ - @Override - protected Class>[] specificSuppliedClasses() - { - Class[] prefSetClasses = - { MetaPref.class, MetaPrefSet.class, MetaPrefBoolean.class, MetaPrefFloat.class, - MetaPrefInt.class, MetaPrefString.class, - - Pref.class, PrefSet.class, PrefBoolean.class, PrefDouble.class, PrefFloat.class, - PrefInt.class, PrefLong.class, PrefString.class, PrefElementState.class, PrefFile.class, - PrefOp.class, - - }; - - return prefSetClasses; - } -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.TranslationsClassProvider; + +/** + * Provides the list of Class'es used for translating the PrefSet class. This class is used to + * provide the base list of Class'es that will be provided to an ApplicationEnvironment. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class PrefSetBaseClassProvider extends TranslationsClassProvider +{ + public static final PrefSetBaseClassProvider STATIC_INSTANCE = new PrefSetBaseClassProvider(); + + protected PrefSetBaseClassProvider() + { + } + + /** + * @see ecologylab.serialization.TranslationsClassProvider#specificSuppliedClasses() + */ + @Override + protected Class>[] specificSuppliedClasses() + { + Class[] prefSetClasses = + { MetaPref.class, MetaPrefSet.class, MetaPrefBoolean.class, MetaPrefFloat.class, + MetaPrefInt.class, MetaPrefString.class, + + Pref.class, PrefSet.class, PrefBoolean.class, PrefDouble.class, PrefFloat.class, + PrefInt.class, PrefLong.class, PrefString.class, PrefElementState.class, PrefFile.class, + PrefOp.class, + + }; + + return prefSetClasses; + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefString.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefString.java index 8932a980..5318f42e 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefString.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefString.java @@ -1,83 +1,83 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Preference that is a String - * - * @author andruid - * - */ -@simpl_inherit -public class PrefString extends Pref -{ - /** - * Value of Pref - */ - @simpl_scalar - String value; - - /** - * - */ - public PrefString() - { - super(); - } - - /** - * Instantiate Pref to value - * - * @param value - */ - public PrefString(String value) - { - super(); - this.value = value; - } - - public PrefString(String name, String value) - { - super(name); - - this.value = value; - } - - /** - * Get the value of the Pref - * - * @return The value of the Pref - */ - @Override - protected String getValue() - { - return value; - } - - /** - * Set the value of the Pref - * - * @param The - * value the Pref will be set to - */ - @Override - public void setValue(String value) - { - this.value = value; - - prefChanged(); - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#clone() - */ - @Override - public Pref clone() - { - return new PrefString(this.name, this.value); - } -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Preference that is a String + * + * @author andruid + * + */ +@simpl_inherit +public class PrefString extends Pref +{ + /** + * Value of Pref + */ + @simpl_scalar + String value; + + /** + * + */ + public PrefString() + { + super(); + } + + /** + * Instantiate Pref to value + * + * @param value + */ + public PrefString(String value) + { + super(); + this.value = value; + } + + public PrefString(String name, String value) + { + super(name); + + this.value = value; + } + + /** + * Get the value of the Pref + * + * @return The value of the Pref + */ + @Override + protected String getValue() + { + return value; + } + + /** + * Set the value of the Pref + * + * @param The + * value the Pref will be set to + */ + @Override + public void setValue(String value) + { + this.value = value; + + prefChanged(); + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#clone() + */ + @Override + public Pref clone() + { + return new PrefString(this.name, this.value); + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefVisual.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefVisual.java index 6cdf88a7..db145937 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefVisual.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefVisual.java @@ -1,739 +1,739 @@ -package ecologylab.appframework.types.prefs; - -import java.awt.Dimension; -import java.awt.Rectangle; - -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; -import javax.swing.JTextField; -import javax.swing.ScrollPaneConstants; -import javax.swing.SwingConstants; - -public class PrefVisual { - - private JTabbedPane jTabbedPane = null; - private JButton jButton = null; // @jve:decl-index=0:visual-constraint="708,77" - private JDialog jDialog = null; // @jve:decl-index=0:visual-constraint="159,42" - private JPanel jContentPane = null; - private JButton jButton1 = null; - private JButton jButton2 = null; - private JButton jButton3 = null; - private JPanel jContentPane1 = null; - private JPanel jContentPane2 = null; - private JPanel jContentPane3 = null; - private JRadioButton crawlYes = null; - private JRadioButton crawlNo = null; - private JLabel crawl = null; - private JLabel download_images_automaticallyLabel = null; - private JRadioButton download_images_automaticallyYes = null; - private JRadioButton download_images_automaticallyNo = null; - private JLabel coolSpaceRatioLabel = null; - private JTextField coolSpaceRatioField = null; - private JLabel spatial_grid = null; - private JRadioButton spatial_gridYes = null; - private JRadioButton spatial_gridNo = null; - private JLabel incontext_slider = null; - private JRadioButton incontext_sliderYes = null; - private JRadioButton incontext_sliderNo = null; - private JLabel dashboard_enabled = null; - private JRadioButton dashboard_enabledYes = null; - private JRadioButton dashboard_enabledNo = null; - private JLabel elements_per_square_inch = null; - private JTextField elements_per_square_inchField = null; - private JLabel undo_levels = null; - private JTextField undo_levelsField = null; - private JLabel log_mode = null; - private JRadioButton log_modeNone = null; - private JRadioButton log_modeDesktop = null; - private JRadioButton log_modeServer = null; - private JLabel javascript_debug_mode = null; - private JRadioButton javascript_debug_modeYes = null; - private JRadioButton javascript_debug_modeNo = null; - private JLabel codebase = null; - private JTextField codebaseField = null; - private JLabel undo_levels1 = null; - private JTextField undo_levelsField1 = null; - private JLabel log_mode1 = null; - private JRadioButton log_modeNone1 = null; - private JRadioButton log_modeDesktop1 = null; - private JRadioButton log_modeServer1 = null; - private JLabel javascript_debug_mode1 = null; - private JRadioButton javascript_debug_modeYes1 = null; - private JRadioButton javascript_debug_modeNo1 = null; - private JLabel codebase1 = null; - private JTextField codebaseField1 = null; - private JScrollPane jScrollPane = null; - /** - * This method initializes jTabbedPane - * - * @return javax.swing.JTabbedPane - */ - private JTabbedPane getJTabbedPane() { - if (jTabbedPane == null) { - jTabbedPane = new JTabbedPane(); - jTabbedPane.setName("jTabbedPane"); - jTabbedPane.setBounds(new Rectangle(0, 0, 595, 416)); - jTabbedPane.addTab("General", null, getJContentPane1(), null); - jTabbedPane.addTab("Gen2", null, getJScrollPane(), null); - jTabbedPane.addTab("Developers", null, getJContentPane2(), null); - } - return jTabbedPane; - } - - /** - * This method initializes jDialog - * - * @return javax.swing.JDialog - */ - private JDialog getJDialog() { - if (jDialog == null) { - jDialog = new JDialog(); - jDialog.setSize(new Dimension(603, 532)); - jDialog.setTitle("combinFormation Preferences"); - jDialog.setContentPane(getJContentPane()); - } - return jDialog; - } - - /** - * This method initializes jContentPane - * - * @return javax.swing.JPanel - */ - private JPanel getJContentPane() { - if (jContentPane == null) { - jContentPane = new JPanel(); - jContentPane.setLayout(null); - jContentPane.add(getJTabbedPane(), null); - jContentPane.add(getJButton1(), null); - jContentPane.add(getJButton2(), null); - jContentPane.add(getJButton3(), null); - } - return jContentPane; - } - - /** - * This method initializes jButton1 - * - * @return javax.swing.JButton - */ - private JButton getJButton1() { - if (jButton1 == null) { - jButton1 = new JButton(); - jButton1.setBounds(new Rectangle(482, 435, 89, 35)); - jButton1.setText("Cancel"); - } - return jButton1; - } - - /** - * This method initializes jButton2 - * - * @return javax.swing.JButton - */ - private JButton getJButton2() { - if (jButton2 == null) { - jButton2 = new JButton(); - jButton2.setBounds(new Rectangle(379, 435, 89, 35)); - jButton2.setText("Save"); - } - return jButton2; - } - - /** - * This method initializes jButton3 - * - * @return javax.swing.JButton - */ - private JButton getJButton3() { - if (jButton3 == null) { - jButton3 = new JButton(); - jButton3.setBounds(new Rectangle(15, 435, 137, 35)); - jButton3.setText("Revert to Default"); - } - return jButton3; - } - - /** - * This method initializes jContentPane1 - * - * @return javax.swing.JPanel - */ - private JPanel getJContentPane1() { - if (jContentPane1 == null) { - elements_per_square_inch = new JLabel(); - elements_per_square_inch.setBounds(new Rectangle(30, 300, 292, 16)); - elements_per_square_inch.setText("Density: Visible elements per square inch [.1,20]"); - elements_per_square_inch.setToolTipText("Controls how many elements will appear in the information space, relative to the area of the space. The default value is .5 elements per square inch.

This lets you decide how many total elements the program will place into the space. Doubling this number, will double the number of elements."); - - dashboard_enabled = new JLabel(); - dashboard_enabled.setBounds(new Rectangle(30, 255, 224, 16)); - dashboard_enabled.setText("Enable the dashboard?"); - dashboard_enabled.setToolTipText("Use the dashboard to modify searches and other seeds."); - - incontext_slider = new JLabel(); - incontext_slider.setBounds(new Rectangle(30, 210, 341, 16)); - incontext_slider.setText("Enable in-context slider?"); - incontext_slider.setToolTipText("Use the in-context slider to enable fine-grained expression of interest in metadata fields and individual words."); - - spatial_grid = new JLabel(); - spatial_grid.setBounds(new Rectangle(30, 165, 366, 16)); - spatial_grid.setText("Composition agent automatically clusters related elements?"); - spatial_grid.setHorizontalTextPosition(SwingConstants.LEADING); - spatial_grid.setToolTipText("Use the visual composition that automatically clusters related elements into piles. You may wish to move elements around, and sometimes, to re-cluster."); - - coolSpaceRatioLabel = new JLabel(); - coolSpaceRatioLabel.setBounds(new Rectangle(30, 120, 187, 16)); - coolSpaceRatioLabel.setToolTipText("The hot space is the composition area that you share with the program. The cool space is exclusively yours to work with.

This parameter defines the proportion of the whole information space that is dedicated as the cool space, at startup time."); - coolSpaceRatioLabel.setText("Cool Space Ratio"); - - download_images_automaticallyLabel = new JLabel(); - download_images_automaticallyLabel.setBounds(new Rectangle(30, 75, 289, 16)); - download_images_automaticallyLabel.setToolTipText("At startup, do you want the information collecting agent to download the images from the web pages it processes?"); - download_images_automaticallyLabel.setText("Download images automatically?"); - - crawl = new JLabel(); - crawl.setBounds(new Rectangle(30, 30, 358, 16)); - crawl.setToolTipText("At startup, do you want the information collecting agent to act as a web crawler, by periodically following hyperlinks to download more documents?"); - crawl.setText("Download linked documents automatically (crawl)?"); - - - - jContentPane1 = new JPanel(); - jContentPane1.setLayout(null); - jContentPane1.add(crawl, null); - jContentPane1.add(getCrawlYes(), null); - jContentPane1.add(getCrawlNo(), null); - jContentPane1.add(download_images_automaticallyLabel, null); - jContentPane1.add(getDownload_images_automaticallyYes(), null); - jContentPane1.add(getDownload_images_automaticallyNo(), null); - jContentPane1.add(coolSpaceRatioLabel, null); - jContentPane1.add(getCoolSpaceRatioField(), null); - jContentPane1.add(spatial_grid, null); - jContentPane1.add(getSpatial_gridYes(), null); - jContentPane1.add(getSpatial_gridNo(), null); - jContentPane1.add(incontext_slider, null); - jContentPane1.add(getIncontext_sliderYes(), null); - jContentPane1.add(getIncontext_sliderNo(), null); - jContentPane1.add(dashboard_enabled, null); - jContentPane1.add(getUse_dashboardYes(), null); - jContentPane1.add(getUse_dashboardNo(), null); - jContentPane1.add(elements_per_square_inch, null); - jContentPane1.add(getElements_per_square_inchField(), null); - } - return jContentPane1; - } - - /** - * This method initializes jContentPane2 - * - * @return javax.swing.JPanel - */ - private JPanel getJContentPane2() { - if (jContentPane2 == null) { - codebase = new JLabel(); - codebase.setBounds(new Rectangle(30, 240, 268, 16)); - codebase.setText("Jar File Directory"); - codebase.setToolTipText("Directory for the project a developer is working on."); - - javascript_debug_mode = new JLabel(); - javascript_debug_mode.setBounds(new Rectangle(30, 180, 197, 16)); - javascript_debug_mode.setText("Javascript Debug Mode"); - javascript_debug_mode.setToolTipText("Shows or hides extra buttons that can be used for debugging the javascript. Allows direct access to cookies & arrays"); - - log_mode = new JLabel(); - log_mode.setBounds(new Rectangle(30, 105, 271, 16)); - log_mode.setText("Log Mode"); - log_mode.setToolTipText("Controls whether or not logging of actions to a file by you and the program is performed during each session. The default is log to Desktop. With this option, you will have trace information available to help us, in case a bug is discovered."); - - undo_levels = new JLabel(); - undo_levels.setBounds(new Rectangle(30, 30, 271, 16)); - undo_levels.setText("Undo Levels"); - undo_levels.setToolTipText("The number of steps backwards you can go, by using undo, or the reverse button."); - - jContentPane2 = new JPanel(); - jContentPane2.setLayout(null); - jContentPane2.setSize(new java.awt.Dimension(586,500)); - jContentPane2.add(undo_levels, null); - jContentPane2.add(getUndo_levelsField(), null); - jContentPane2.add(log_mode, null); - jContentPane2.add(getLog_modeNone(), null); - jContentPane2.add(getLog_modeDesktop(), null); - jContentPane2.add(getLog_modeServer(), null); - jContentPane2.add(javascript_debug_mode, null); - jContentPane2.add(getJavascript_debug_modeYes(), null); - jContentPane2.add(getJavascript_debug_modeNo(), null); - jContentPane2.add(codebase, null); - jContentPane2.add(getCodebaseField(), null); - } - return jContentPane2; - } - - /** - * This method initializes jContentPane2 - * - * @return javax.swing.JPanel - */ - private JPanel getJContentPane3() { - if (jContentPane3 == null) { - codebase1 = new JLabel(); - codebase1.setBounds(new Rectangle(30, 240, 268, 16)); - codebase1.setText("Jar File Directory"); - codebase1.setToolTipText("Directory for the project a developer is working on."); - - javascript_debug_mode1 = new JLabel(); - javascript_debug_mode1.setBounds(new Rectangle(30, 180, 197, 16)); - javascript_debug_mode1.setText("Javascript Debug Mode"); - javascript_debug_mode1.setToolTipText("Shows or hides extra buttons that can be used for debugging the javascript. Allows direct access to cookies & arrays"); - - log_mode1 = new JLabel(); - log_mode1.setBounds(new Rectangle(30, 105, 271, 16)); - log_mode1.setText("Log Mode"); - log_mode1.setToolTipText("Controls whether or not logging of actions to a file by you and the program is performed during each session. The default is log to Desktop. With this option, you will have trace information available to help us, in case a bug is discovered."); - - undo_levels1 = new JLabel(); - undo_levels1.setBounds(new Rectangle(30, 30, 271, 16)); - undo_levels1.setText("Undo Levels"); - undo_levels1.setToolTipText("The number of steps backwards you can go, by using undo, or the reverse button."); - - jContentPane3 = new JPanel(); - jContentPane3.setLayout(null); - jContentPane3.setSize(new java.awt.Dimension(586,500)); - jContentPane3.add(undo_levels1, null); - jContentPane3.add(getUndo_levelsField1(), null); - jContentPane3.add(log_mode1, null); - jContentPane3.add(getLog_modeNone1(), null); - jContentPane3.add(getLog_modeDesktop1(), null); - jContentPane3.add(getLog_modeServer1(), null); - jContentPane3.add(javascript_debug_mode1, null); - jContentPane3.add(getJavascript_debug_modeYes1(), null); - jContentPane3.add(getJavascript_debug_modeNo1(), null); - jContentPane3.add(codebase1, null); - jContentPane3.add(getCodebaseField1(), null); - } - return jContentPane3; - } - - /** - * This method initializes crawlYes - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getCrawlYes() { - if (crawlYes == null) { - crawlYes = new JRadioButton(); - crawlYes.setBounds(new Rectangle(417, 28, 54, 21)); - crawlYes.setSelected(true); - crawlYes.setText("Yes"); - } - return crawlYes; - } - - /** - * This method initializes crawlNo - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getCrawlNo() { - if (crawlNo == null) { - crawlNo = new JRadioButton(); - crawlNo.setBounds(new Rectangle(493, 28, 46, 21)); - crawlNo.setName("No"); - crawlNo.setText("No"); - } - return crawlNo; - } - - /** - * This method initializes download_images_automaticallyYes - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getDownload_images_automaticallyYes() { - if (download_images_automaticallyYes == null) { - download_images_automaticallyYes = new JRadioButton(); - download_images_automaticallyYes.setBounds(new Rectangle(418, 70, 46, 24)); - download_images_automaticallyYes.setSelected(true); - download_images_automaticallyYes.setText("Yes"); - } - return download_images_automaticallyYes; - } - - /** - * This method initializes download_images_automaticallyNo - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getDownload_images_automaticallyNo() { - if (download_images_automaticallyNo == null) { - download_images_automaticallyNo = new JRadioButton(); - download_images_automaticallyNo.setBounds(new Rectangle(494, 70, 40, 24)); - download_images_automaticallyNo.setText("No"); - download_images_automaticallyNo.setName("No"); - } - return download_images_automaticallyNo; - } - - /** - * This method initializes coolSpaceRatioField - * - * @return javax.swing.JTextField - */ - private JTextField getCoolSpaceRatioField() { - if (coolSpaceRatioField == null) { - coolSpaceRatioField = new JTextField(); - coolSpaceRatioField.setBounds(new Rectangle(451, 118, 55, 20)); - coolSpaceRatioField.setHorizontalAlignment(SwingConstants.CENTER); - coolSpaceRatioField.setText("0.2"); - } - return coolSpaceRatioField; - } - - /** - * This method initializes spatial_gridYes - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getSpatial_gridYes() { - if (spatial_gridYes == null) { - spatial_gridYes = new JRadioButton(); - spatial_gridYes.setBounds(new Rectangle(419, 162, 46, 24)); - spatial_gridYes.setText("Yes"); - spatial_gridYes.setSelected(true); - } - return spatial_gridYes; - } - - /** - * This method initializes spatial_gridNo - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getSpatial_gridNo() { - if (spatial_gridNo == null) { - spatial_gridNo = new JRadioButton(); - spatial_gridNo.setBounds(new Rectangle(494, 161, 40, 24)); - spatial_gridNo.setText("No"); - spatial_gridNo.setName("No"); - } - return spatial_gridNo; - } - - /** - * This method initializes incontext_sliderYes - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getIncontext_sliderYes() { - if (incontext_sliderYes == null) { - incontext_sliderYes = new JRadioButton(); - incontext_sliderYes.setBounds(new Rectangle(419, 206, 46, 24)); - incontext_sliderYes.setText("Yes"); - incontext_sliderYes.setEnabled(true); - incontext_sliderYes.setSelected(false); - } - return incontext_sliderYes; - } - - /** - * This method initializes incontext_sliderNo - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getIncontext_sliderNo() { - if (incontext_sliderNo == null) { - incontext_sliderNo = new JRadioButton(); - incontext_sliderNo.setBounds(new Rectangle(494, 206, 40, 24)); - incontext_sliderNo.setText("No"); - incontext_sliderNo.setSelected(true); - incontext_sliderNo.setName("No"); - } - return incontext_sliderNo; - } - - /** - * This method initializes use_dashboardYes - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getUse_dashboardYes() { - if (dashboard_enabledYes == null) { - dashboard_enabledYes = new JRadioButton(); - dashboard_enabledYes.setBounds(new Rectangle(419, 251, 46, 24)); - dashboard_enabledYes.setSelected(false); - dashboard_enabledYes.setText("Yes"); - dashboard_enabledYes.setEnabled(true); - } - return dashboard_enabledYes; - } - - /** - * This method initializes use_dashboardNo - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getUse_dashboardNo() { - if (dashboard_enabledNo == null) { - dashboard_enabledNo = new JRadioButton(); - dashboard_enabledNo.setBounds(new Rectangle(494, 251, 40, 24)); - dashboard_enabledNo.setSelected(true); - dashboard_enabledNo.setText("No"); - dashboard_enabledNo.setName("No"); - } - return dashboard_enabledNo; - } - - /** - * This method initializes elements_per_square_inchField - * - * @return javax.swing.JTextField - */ - private JTextField getElements_per_square_inchField() { - if (elements_per_square_inchField == null) { - elements_per_square_inchField = new JTextField(); - elements_per_square_inchField.setBounds(new Rectangle(451, 298, 55, 20)); - elements_per_square_inchField.setHorizontalAlignment(SwingConstants.CENTER); - elements_per_square_inchField.setText("0.7"); - } - return elements_per_square_inchField; - } - - /** - * This method initializes undo_levelsField - * - * @return javax.swing.JTextField - */ - private JTextField getUndo_levelsField() { - if (undo_levelsField == null) { - undo_levelsField = new JTextField(); - undo_levelsField.setBounds(new Rectangle(451, 28, 55, 20)); - undo_levelsField.setHorizontalAlignment(SwingConstants.CENTER); - undo_levelsField.setText("32"); - } - return undo_levelsField; - } - - /** - * This method initializes log_modeNone - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getLog_modeNone() { - if (log_modeNone == null) { - log_modeNone = new JRadioButton(); - log_modeNone.setBounds(new Rectangle(417, 78, 85, 24)); - log_modeNone.setText("no logging"); - log_modeNone.setHorizontalTextPosition(SwingConstants.TRAILING); - log_modeNone.setSelected(false); - } - return log_modeNone; - } - - /** - * This method initializes log_modeDesktop - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getLog_modeDesktop() { - if (log_modeDesktop == null) { - log_modeDesktop = new JRadioButton(); - log_modeDesktop.setBounds(new Rectangle(417, 100, 131, 24)); - log_modeDesktop.setSelected(true); - log_modeDesktop.setText("log to desktop file"); - log_modeDesktop.setHorizontalTextPosition(SwingConstants.TRAILING); - } - return log_modeDesktop; - } - - /** - * This method initializes log_modeServer - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getLog_modeServer() { - if (log_modeServer == null) { - log_modeServer = new JRadioButton(); - log_modeServer.setBounds(new Rectangle(417, 122, 148, 24)); - log_modeServer.setSelected(false); - log_modeServer.setText("log to logging server"); - log_modeServer.setHorizontalTextPosition(SwingConstants.TRAILING); - } - return log_modeServer; - } - - /** - * This method initializes javascript_debug_modeYes - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getJavascript_debug_modeYes() { - if (javascript_debug_modeYes == null) { - javascript_debug_modeYes = new JRadioButton(); - javascript_debug_modeYes.setBounds(new Rectangle(417, 176, 46, 24)); - javascript_debug_modeYes.setText("Yes"); - javascript_debug_modeYes.setSelected(true); - } - return javascript_debug_modeYes; - } - - /** - * This method initializes javascript_debug_modeNo - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getJavascript_debug_modeNo() { - if (javascript_debug_modeNo == null) { - javascript_debug_modeNo = new JRadioButton(); - javascript_debug_modeNo.setBounds(new Rectangle(494, 176, 40, 24)); - javascript_debug_modeNo.setText("No"); - javascript_debug_modeNo.setName("No"); - } - return javascript_debug_modeNo; - } - - /** - * This method initializes codebaseField - * - * @return javax.swing.JTextField - */ - private JTextField getCodebaseField() { - if (codebaseField == null) { - codebaseField = new JTextField(); - codebaseField.setHorizontalAlignment(SwingConstants.CENTER); - codebaseField.setBounds(new java.awt.Rectangle(421,238,114,20)); - codebaseField.setText("code/java"); - } - return codebaseField; - } - - /** - * This method initializes undo_levelsField - * - * @return javax.swing.JTextField - */ - private JTextField getUndo_levelsField1() { - if (undo_levelsField1 == null) { - undo_levelsField1 = new JTextField(); - undo_levelsField1.setBounds(new Rectangle(451, 28, 55, 20)); - undo_levelsField1.setHorizontalAlignment(SwingConstants.CENTER); - undo_levelsField1.setText("32"); - } - return undo_levelsField1; - } - - /** - * This method initializes log_modeNone - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getLog_modeNone1() { - if (log_modeNone1 == null) { - log_modeNone1 = new JRadioButton(); - log_modeNone1.setBounds(new Rectangle(417, 78, 85, 24)); - log_modeNone1.setText("no logging"); - log_modeNone1.setHorizontalTextPosition(SwingConstants.TRAILING); - log_modeNone1.setSelected(false); - } - return log_modeNone1; - } - - /** - * This method initializes log_modeDesktop - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getLog_modeDesktop1() { - if (log_modeDesktop1 == null) { - log_modeDesktop1 = new JRadioButton(); - log_modeDesktop1.setBounds(new Rectangle(417, 100, 131, 24)); - log_modeDesktop1.setSelected(true); - log_modeDesktop1.setText("log to desktop file"); - log_modeDesktop1.setHorizontalTextPosition(SwingConstants.TRAILING); - } - return log_modeDesktop1; - } - - /** - * This method initializes log_modeServer - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getLog_modeServer1() { - if (log_modeServer1 == null) { - log_modeServer1 = new JRadioButton(); - log_modeServer1.setBounds(new Rectangle(417, 122, 148, 24)); - log_modeServer1.setSelected(false); - log_modeServer1.setText("log to logging server"); - log_modeServer1.setHorizontalTextPosition(SwingConstants.TRAILING); - } - return log_modeServer1; - } - - /** - * This method initializes javascript_debug_modeYes - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getJavascript_debug_modeYes1() { - if (javascript_debug_modeYes1 == null) { - javascript_debug_modeYes1 = new JRadioButton(); - javascript_debug_modeYes1.setBounds(new Rectangle(417, 176, 46, 24)); - javascript_debug_modeYes1.setText("Yes"); - javascript_debug_modeYes1.setSelected(true); - } - return javascript_debug_modeYes1; - } - - /** - * This method initializes javascript_debug_modeNo - * - * @return javax.swing.JRadioButton - */ - private JRadioButton getJavascript_debug_modeNo1() { - if (javascript_debug_modeNo1 == null) { - javascript_debug_modeNo1 = new JRadioButton(); - javascript_debug_modeNo1.setBounds(new Rectangle(494, 176, 40, 24)); - javascript_debug_modeNo1.setText("No"); - javascript_debug_modeNo1.setName("No"); - } - return javascript_debug_modeNo1; - } - - /** - * This method initializes codebaseField - * - * @return javax.swing.JTextField - */ - private JTextField getCodebaseField1() { - if (codebaseField1 == null) { - codebaseField1 = new JTextField(); - codebaseField1.setHorizontalAlignment(SwingConstants.CENTER); - codebaseField1.setBounds(new java.awt.Rectangle(421,238,114,20)); - codebaseField1.setText("code/java"); - } - return codebaseField1; - } - - /** - * This method initializes jScrollPane - * - * @return javax.swing.JScrollPane - */ - private JScrollPane getJScrollPane() { - if (jScrollPane == null) { - jScrollPane = new JScrollPane(); - jScrollPane.setPreferredSize(new java.awt.Dimension(500,500)); - jScrollPane.setComponentOrientation(java.awt.ComponentOrientation.LEFT_TO_RIGHT); - jScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - jScrollPane.setName(""); - jScrollPane.setViewportView(getJContentPane3()); - } - return jScrollPane; - } - -} +package ecologylab.appframework.types.prefs; + +import java.awt.Dimension; +import java.awt.Rectangle; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextField; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingConstants; + +public class PrefVisual { + + private JTabbedPane jTabbedPane = null; + private JButton jButton = null; // @jve:decl-index=0:visual-constraint="708,77" + private JDialog jDialog = null; // @jve:decl-index=0:visual-constraint="159,42" + private JPanel jContentPane = null; + private JButton jButton1 = null; + private JButton jButton2 = null; + private JButton jButton3 = null; + private JPanel jContentPane1 = null; + private JPanel jContentPane2 = null; + private JPanel jContentPane3 = null; + private JRadioButton crawlYes = null; + private JRadioButton crawlNo = null; + private JLabel crawl = null; + private JLabel download_images_automaticallyLabel = null; + private JRadioButton download_images_automaticallyYes = null; + private JRadioButton download_images_automaticallyNo = null; + private JLabel coolSpaceRatioLabel = null; + private JTextField coolSpaceRatioField = null; + private JLabel spatial_grid = null; + private JRadioButton spatial_gridYes = null; + private JRadioButton spatial_gridNo = null; + private JLabel incontext_slider = null; + private JRadioButton incontext_sliderYes = null; + private JRadioButton incontext_sliderNo = null; + private JLabel dashboard_enabled = null; + private JRadioButton dashboard_enabledYes = null; + private JRadioButton dashboard_enabledNo = null; + private JLabel elements_per_square_inch = null; + private JTextField elements_per_square_inchField = null; + private JLabel undo_levels = null; + private JTextField undo_levelsField = null; + private JLabel log_mode = null; + private JRadioButton log_modeNone = null; + private JRadioButton log_modeDesktop = null; + private JRadioButton log_modeServer = null; + private JLabel javascript_debug_mode = null; + private JRadioButton javascript_debug_modeYes = null; + private JRadioButton javascript_debug_modeNo = null; + private JLabel codebase = null; + private JTextField codebaseField = null; + private JLabel undo_levels1 = null; + private JTextField undo_levelsField1 = null; + private JLabel log_mode1 = null; + private JRadioButton log_modeNone1 = null; + private JRadioButton log_modeDesktop1 = null; + private JRadioButton log_modeServer1 = null; + private JLabel javascript_debug_mode1 = null; + private JRadioButton javascript_debug_modeYes1 = null; + private JRadioButton javascript_debug_modeNo1 = null; + private JLabel codebase1 = null; + private JTextField codebaseField1 = null; + private JScrollPane jScrollPane = null; + /** + * This method initializes jTabbedPane + * + * @return javax.swing.JTabbedPane + */ + private JTabbedPane getJTabbedPane() { + if (jTabbedPane == null) { + jTabbedPane = new JTabbedPane(); + jTabbedPane.setName("jTabbedPane"); + jTabbedPane.setBounds(new Rectangle(0, 0, 595, 416)); + jTabbedPane.addTab("General", null, getJContentPane1(), null); + jTabbedPane.addTab("Gen2", null, getJScrollPane(), null); + jTabbedPane.addTab("Developers", null, getJContentPane2(), null); + } + return jTabbedPane; + } + + /** + * This method initializes jDialog + * + * @return javax.swing.JDialog + */ + private JDialog getJDialog() { + if (jDialog == null) { + jDialog = new JDialog(); + jDialog.setSize(new Dimension(603, 532)); + jDialog.setTitle("combinFormation Preferences"); + jDialog.setContentPane(getJContentPane()); + } + return jDialog; + } + + /** + * This method initializes jContentPane + * + * @return javax.swing.JPanel + */ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJTabbedPane(), null); + jContentPane.add(getJButton1(), null); + jContentPane.add(getJButton2(), null); + jContentPane.add(getJButton3(), null); + } + return jContentPane; + } + + /** + * This method initializes jButton1 + * + * @return javax.swing.JButton + */ + private JButton getJButton1() { + if (jButton1 == null) { + jButton1 = new JButton(); + jButton1.setBounds(new Rectangle(482, 435, 89, 35)); + jButton1.setText("Cancel"); + } + return jButton1; + } + + /** + * This method initializes jButton2 + * + * @return javax.swing.JButton + */ + private JButton getJButton2() { + if (jButton2 == null) { + jButton2 = new JButton(); + jButton2.setBounds(new Rectangle(379, 435, 89, 35)); + jButton2.setText("Save"); + } + return jButton2; + } + + /** + * This method initializes jButton3 + * + * @return javax.swing.JButton + */ + private JButton getJButton3() { + if (jButton3 == null) { + jButton3 = new JButton(); + jButton3.setBounds(new Rectangle(15, 435, 137, 35)); + jButton3.setText("Revert to Default"); + } + return jButton3; + } + + /** + * This method initializes jContentPane1 + * + * @return javax.swing.JPanel + */ + private JPanel getJContentPane1() { + if (jContentPane1 == null) { + elements_per_square_inch = new JLabel(); + elements_per_square_inch.setBounds(new Rectangle(30, 300, 292, 16)); + elements_per_square_inch.setText("Density: Visible elements per square inch [.1,20]"); + elements_per_square_inch.setToolTipText("Controls how many elements will appear in the information space, relative to the area of the space. The default value is .5 elements per square inch.

This lets you decide how many total elements the program will place into the space. Doubling this number, will double the number of elements."); + + dashboard_enabled = new JLabel(); + dashboard_enabled.setBounds(new Rectangle(30, 255, 224, 16)); + dashboard_enabled.setText("Enable the dashboard?"); + dashboard_enabled.setToolTipText("Use the dashboard to modify searches and other seeds."); + + incontext_slider = new JLabel(); + incontext_slider.setBounds(new Rectangle(30, 210, 341, 16)); + incontext_slider.setText("Enable in-context slider?"); + incontext_slider.setToolTipText("Use the in-context slider to enable fine-grained expression of interest in metadata fields and individual words."); + + spatial_grid = new JLabel(); + spatial_grid.setBounds(new Rectangle(30, 165, 366, 16)); + spatial_grid.setText("Composition agent automatically clusters related elements?"); + spatial_grid.setHorizontalTextPosition(SwingConstants.LEADING); + spatial_grid.setToolTipText("Use the visual composition that automatically clusters related elements into piles. You may wish to move elements around, and sometimes, to re-cluster."); + + coolSpaceRatioLabel = new JLabel(); + coolSpaceRatioLabel.setBounds(new Rectangle(30, 120, 187, 16)); + coolSpaceRatioLabel.setToolTipText("The hot space is the composition area that you share with the program. The cool space is exclusively yours to work with.

This parameter defines the proportion of the whole information space that is dedicated as the cool space, at startup time."); + coolSpaceRatioLabel.setText("Cool Space Ratio"); + + download_images_automaticallyLabel = new JLabel(); + download_images_automaticallyLabel.setBounds(new Rectangle(30, 75, 289, 16)); + download_images_automaticallyLabel.setToolTipText("At startup, do you want the information collecting agent to download the images from the web pages it processes?"); + download_images_automaticallyLabel.setText("Download images automatically?"); + + crawl = new JLabel(); + crawl.setBounds(new Rectangle(30, 30, 358, 16)); + crawl.setToolTipText("At startup, do you want the information collecting agent to act as a web crawler, by periodically following hyperlinks to download more documents?"); + crawl.setText("Download linked documents automatically (crawl)?"); + + + + jContentPane1 = new JPanel(); + jContentPane1.setLayout(null); + jContentPane1.add(crawl, null); + jContentPane1.add(getCrawlYes(), null); + jContentPane1.add(getCrawlNo(), null); + jContentPane1.add(download_images_automaticallyLabel, null); + jContentPane1.add(getDownload_images_automaticallyYes(), null); + jContentPane1.add(getDownload_images_automaticallyNo(), null); + jContentPane1.add(coolSpaceRatioLabel, null); + jContentPane1.add(getCoolSpaceRatioField(), null); + jContentPane1.add(spatial_grid, null); + jContentPane1.add(getSpatial_gridYes(), null); + jContentPane1.add(getSpatial_gridNo(), null); + jContentPane1.add(incontext_slider, null); + jContentPane1.add(getIncontext_sliderYes(), null); + jContentPane1.add(getIncontext_sliderNo(), null); + jContentPane1.add(dashboard_enabled, null); + jContentPane1.add(getUse_dashboardYes(), null); + jContentPane1.add(getUse_dashboardNo(), null); + jContentPane1.add(elements_per_square_inch, null); + jContentPane1.add(getElements_per_square_inchField(), null); + } + return jContentPane1; + } + + /** + * This method initializes jContentPane2 + * + * @return javax.swing.JPanel + */ + private JPanel getJContentPane2() { + if (jContentPane2 == null) { + codebase = new JLabel(); + codebase.setBounds(new Rectangle(30, 240, 268, 16)); + codebase.setText("Jar File Directory"); + codebase.setToolTipText("Directory for the project a developer is working on."); + + javascript_debug_mode = new JLabel(); + javascript_debug_mode.setBounds(new Rectangle(30, 180, 197, 16)); + javascript_debug_mode.setText("Javascript Debug Mode"); + javascript_debug_mode.setToolTipText("Shows or hides extra buttons that can be used for debugging the javascript. Allows direct access to cookies & arrays"); + + log_mode = new JLabel(); + log_mode.setBounds(new Rectangle(30, 105, 271, 16)); + log_mode.setText("Log Mode"); + log_mode.setToolTipText("Controls whether or not logging of actions to a file by you and the program is performed during each session. The default is log to Desktop. With this option, you will have trace information available to help us, in case a bug is discovered."); + + undo_levels = new JLabel(); + undo_levels.setBounds(new Rectangle(30, 30, 271, 16)); + undo_levels.setText("Undo Levels"); + undo_levels.setToolTipText("The number of steps backwards you can go, by using undo, or the reverse button."); + + jContentPane2 = new JPanel(); + jContentPane2.setLayout(null); + jContentPane2.setSize(new java.awt.Dimension(586,500)); + jContentPane2.add(undo_levels, null); + jContentPane2.add(getUndo_levelsField(), null); + jContentPane2.add(log_mode, null); + jContentPane2.add(getLog_modeNone(), null); + jContentPane2.add(getLog_modeDesktop(), null); + jContentPane2.add(getLog_modeServer(), null); + jContentPane2.add(javascript_debug_mode, null); + jContentPane2.add(getJavascript_debug_modeYes(), null); + jContentPane2.add(getJavascript_debug_modeNo(), null); + jContentPane2.add(codebase, null); + jContentPane2.add(getCodebaseField(), null); + } + return jContentPane2; + } + + /** + * This method initializes jContentPane2 + * + * @return javax.swing.JPanel + */ + private JPanel getJContentPane3() { + if (jContentPane3 == null) { + codebase1 = new JLabel(); + codebase1.setBounds(new Rectangle(30, 240, 268, 16)); + codebase1.setText("Jar File Directory"); + codebase1.setToolTipText("Directory for the project a developer is working on."); + + javascript_debug_mode1 = new JLabel(); + javascript_debug_mode1.setBounds(new Rectangle(30, 180, 197, 16)); + javascript_debug_mode1.setText("Javascript Debug Mode"); + javascript_debug_mode1.setToolTipText("Shows or hides extra buttons that can be used for debugging the javascript. Allows direct access to cookies & arrays"); + + log_mode1 = new JLabel(); + log_mode1.setBounds(new Rectangle(30, 105, 271, 16)); + log_mode1.setText("Log Mode"); + log_mode1.setToolTipText("Controls whether or not logging of actions to a file by you and the program is performed during each session. The default is log to Desktop. With this option, you will have trace information available to help us, in case a bug is discovered."); + + undo_levels1 = new JLabel(); + undo_levels1.setBounds(new Rectangle(30, 30, 271, 16)); + undo_levels1.setText("Undo Levels"); + undo_levels1.setToolTipText("The number of steps backwards you can go, by using undo, or the reverse button."); + + jContentPane3 = new JPanel(); + jContentPane3.setLayout(null); + jContentPane3.setSize(new java.awt.Dimension(586,500)); + jContentPane3.add(undo_levels1, null); + jContentPane3.add(getUndo_levelsField1(), null); + jContentPane3.add(log_mode1, null); + jContentPane3.add(getLog_modeNone1(), null); + jContentPane3.add(getLog_modeDesktop1(), null); + jContentPane3.add(getLog_modeServer1(), null); + jContentPane3.add(javascript_debug_mode1, null); + jContentPane3.add(getJavascript_debug_modeYes1(), null); + jContentPane3.add(getJavascript_debug_modeNo1(), null); + jContentPane3.add(codebase1, null); + jContentPane3.add(getCodebaseField1(), null); + } + return jContentPane3; + } + + /** + * This method initializes crawlYes + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getCrawlYes() { + if (crawlYes == null) { + crawlYes = new JRadioButton(); + crawlYes.setBounds(new Rectangle(417, 28, 54, 21)); + crawlYes.setSelected(true); + crawlYes.setText("Yes"); + } + return crawlYes; + } + + /** + * This method initializes crawlNo + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getCrawlNo() { + if (crawlNo == null) { + crawlNo = new JRadioButton(); + crawlNo.setBounds(new Rectangle(493, 28, 46, 21)); + crawlNo.setName("No"); + crawlNo.setText("No"); + } + return crawlNo; + } + + /** + * This method initializes download_images_automaticallyYes + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getDownload_images_automaticallyYes() { + if (download_images_automaticallyYes == null) { + download_images_automaticallyYes = new JRadioButton(); + download_images_automaticallyYes.setBounds(new Rectangle(418, 70, 46, 24)); + download_images_automaticallyYes.setSelected(true); + download_images_automaticallyYes.setText("Yes"); + } + return download_images_automaticallyYes; + } + + /** + * This method initializes download_images_automaticallyNo + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getDownload_images_automaticallyNo() { + if (download_images_automaticallyNo == null) { + download_images_automaticallyNo = new JRadioButton(); + download_images_automaticallyNo.setBounds(new Rectangle(494, 70, 40, 24)); + download_images_automaticallyNo.setText("No"); + download_images_automaticallyNo.setName("No"); + } + return download_images_automaticallyNo; + } + + /** + * This method initializes coolSpaceRatioField + * + * @return javax.swing.JTextField + */ + private JTextField getCoolSpaceRatioField() { + if (coolSpaceRatioField == null) { + coolSpaceRatioField = new JTextField(); + coolSpaceRatioField.setBounds(new Rectangle(451, 118, 55, 20)); + coolSpaceRatioField.setHorizontalAlignment(SwingConstants.CENTER); + coolSpaceRatioField.setText("0.2"); + } + return coolSpaceRatioField; + } + + /** + * This method initializes spatial_gridYes + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getSpatial_gridYes() { + if (spatial_gridYes == null) { + spatial_gridYes = new JRadioButton(); + spatial_gridYes.setBounds(new Rectangle(419, 162, 46, 24)); + spatial_gridYes.setText("Yes"); + spatial_gridYes.setSelected(true); + } + return spatial_gridYes; + } + + /** + * This method initializes spatial_gridNo + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getSpatial_gridNo() { + if (spatial_gridNo == null) { + spatial_gridNo = new JRadioButton(); + spatial_gridNo.setBounds(new Rectangle(494, 161, 40, 24)); + spatial_gridNo.setText("No"); + spatial_gridNo.setName("No"); + } + return spatial_gridNo; + } + + /** + * This method initializes incontext_sliderYes + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getIncontext_sliderYes() { + if (incontext_sliderYes == null) { + incontext_sliderYes = new JRadioButton(); + incontext_sliderYes.setBounds(new Rectangle(419, 206, 46, 24)); + incontext_sliderYes.setText("Yes"); + incontext_sliderYes.setEnabled(true); + incontext_sliderYes.setSelected(false); + } + return incontext_sliderYes; + } + + /** + * This method initializes incontext_sliderNo + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getIncontext_sliderNo() { + if (incontext_sliderNo == null) { + incontext_sliderNo = new JRadioButton(); + incontext_sliderNo.setBounds(new Rectangle(494, 206, 40, 24)); + incontext_sliderNo.setText("No"); + incontext_sliderNo.setSelected(true); + incontext_sliderNo.setName("No"); + } + return incontext_sliderNo; + } + + /** + * This method initializes use_dashboardYes + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getUse_dashboardYes() { + if (dashboard_enabledYes == null) { + dashboard_enabledYes = new JRadioButton(); + dashboard_enabledYes.setBounds(new Rectangle(419, 251, 46, 24)); + dashboard_enabledYes.setSelected(false); + dashboard_enabledYes.setText("Yes"); + dashboard_enabledYes.setEnabled(true); + } + return dashboard_enabledYes; + } + + /** + * This method initializes use_dashboardNo + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getUse_dashboardNo() { + if (dashboard_enabledNo == null) { + dashboard_enabledNo = new JRadioButton(); + dashboard_enabledNo.setBounds(new Rectangle(494, 251, 40, 24)); + dashboard_enabledNo.setSelected(true); + dashboard_enabledNo.setText("No"); + dashboard_enabledNo.setName("No"); + } + return dashboard_enabledNo; + } + + /** + * This method initializes elements_per_square_inchField + * + * @return javax.swing.JTextField + */ + private JTextField getElements_per_square_inchField() { + if (elements_per_square_inchField == null) { + elements_per_square_inchField = new JTextField(); + elements_per_square_inchField.setBounds(new Rectangle(451, 298, 55, 20)); + elements_per_square_inchField.setHorizontalAlignment(SwingConstants.CENTER); + elements_per_square_inchField.setText("0.7"); + } + return elements_per_square_inchField; + } + + /** + * This method initializes undo_levelsField + * + * @return javax.swing.JTextField + */ + private JTextField getUndo_levelsField() { + if (undo_levelsField == null) { + undo_levelsField = new JTextField(); + undo_levelsField.setBounds(new Rectangle(451, 28, 55, 20)); + undo_levelsField.setHorizontalAlignment(SwingConstants.CENTER); + undo_levelsField.setText("32"); + } + return undo_levelsField; + } + + /** + * This method initializes log_modeNone + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getLog_modeNone() { + if (log_modeNone == null) { + log_modeNone = new JRadioButton(); + log_modeNone.setBounds(new Rectangle(417, 78, 85, 24)); + log_modeNone.setText("no logging"); + log_modeNone.setHorizontalTextPosition(SwingConstants.TRAILING); + log_modeNone.setSelected(false); + } + return log_modeNone; + } + + /** + * This method initializes log_modeDesktop + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getLog_modeDesktop() { + if (log_modeDesktop == null) { + log_modeDesktop = new JRadioButton(); + log_modeDesktop.setBounds(new Rectangle(417, 100, 131, 24)); + log_modeDesktop.setSelected(true); + log_modeDesktop.setText("log to desktop file"); + log_modeDesktop.setHorizontalTextPosition(SwingConstants.TRAILING); + } + return log_modeDesktop; + } + + /** + * This method initializes log_modeServer + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getLog_modeServer() { + if (log_modeServer == null) { + log_modeServer = new JRadioButton(); + log_modeServer.setBounds(new Rectangle(417, 122, 148, 24)); + log_modeServer.setSelected(false); + log_modeServer.setText("log to logging server"); + log_modeServer.setHorizontalTextPosition(SwingConstants.TRAILING); + } + return log_modeServer; + } + + /** + * This method initializes javascript_debug_modeYes + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getJavascript_debug_modeYes() { + if (javascript_debug_modeYes == null) { + javascript_debug_modeYes = new JRadioButton(); + javascript_debug_modeYes.setBounds(new Rectangle(417, 176, 46, 24)); + javascript_debug_modeYes.setText("Yes"); + javascript_debug_modeYes.setSelected(true); + } + return javascript_debug_modeYes; + } + + /** + * This method initializes javascript_debug_modeNo + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getJavascript_debug_modeNo() { + if (javascript_debug_modeNo == null) { + javascript_debug_modeNo = new JRadioButton(); + javascript_debug_modeNo.setBounds(new Rectangle(494, 176, 40, 24)); + javascript_debug_modeNo.setText("No"); + javascript_debug_modeNo.setName("No"); + } + return javascript_debug_modeNo; + } + + /** + * This method initializes codebaseField + * + * @return javax.swing.JTextField + */ + private JTextField getCodebaseField() { + if (codebaseField == null) { + codebaseField = new JTextField(); + codebaseField.setHorizontalAlignment(SwingConstants.CENTER); + codebaseField.setBounds(new java.awt.Rectangle(421,238,114,20)); + codebaseField.setText("code/java"); + } + return codebaseField; + } + + /** + * This method initializes undo_levelsField + * + * @return javax.swing.JTextField + */ + private JTextField getUndo_levelsField1() { + if (undo_levelsField1 == null) { + undo_levelsField1 = new JTextField(); + undo_levelsField1.setBounds(new Rectangle(451, 28, 55, 20)); + undo_levelsField1.setHorizontalAlignment(SwingConstants.CENTER); + undo_levelsField1.setText("32"); + } + return undo_levelsField1; + } + + /** + * This method initializes log_modeNone + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getLog_modeNone1() { + if (log_modeNone1 == null) { + log_modeNone1 = new JRadioButton(); + log_modeNone1.setBounds(new Rectangle(417, 78, 85, 24)); + log_modeNone1.setText("no logging"); + log_modeNone1.setHorizontalTextPosition(SwingConstants.TRAILING); + log_modeNone1.setSelected(false); + } + return log_modeNone1; + } + + /** + * This method initializes log_modeDesktop + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getLog_modeDesktop1() { + if (log_modeDesktop1 == null) { + log_modeDesktop1 = new JRadioButton(); + log_modeDesktop1.setBounds(new Rectangle(417, 100, 131, 24)); + log_modeDesktop1.setSelected(true); + log_modeDesktop1.setText("log to desktop file"); + log_modeDesktop1.setHorizontalTextPosition(SwingConstants.TRAILING); + } + return log_modeDesktop1; + } + + /** + * This method initializes log_modeServer + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getLog_modeServer1() { + if (log_modeServer1 == null) { + log_modeServer1 = new JRadioButton(); + log_modeServer1.setBounds(new Rectangle(417, 122, 148, 24)); + log_modeServer1.setSelected(false); + log_modeServer1.setText("log to logging server"); + log_modeServer1.setHorizontalTextPosition(SwingConstants.TRAILING); + } + return log_modeServer1; + } + + /** + * This method initializes javascript_debug_modeYes + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getJavascript_debug_modeYes1() { + if (javascript_debug_modeYes1 == null) { + javascript_debug_modeYes1 = new JRadioButton(); + javascript_debug_modeYes1.setBounds(new Rectangle(417, 176, 46, 24)); + javascript_debug_modeYes1.setText("Yes"); + javascript_debug_modeYes1.setSelected(true); + } + return javascript_debug_modeYes1; + } + + /** + * This method initializes javascript_debug_modeNo + * + * @return javax.swing.JRadioButton + */ + private JRadioButton getJavascript_debug_modeNo1() { + if (javascript_debug_modeNo1 == null) { + javascript_debug_modeNo1 = new JRadioButton(); + javascript_debug_modeNo1.setBounds(new Rectangle(494, 176, 40, 24)); + javascript_debug_modeNo1.setText("No"); + javascript_debug_modeNo1.setName("No"); + } + return javascript_debug_modeNo1; + } + + /** + * This method initializes codebaseField + * + * @return javax.swing.JTextField + */ + private JTextField getCodebaseField1() { + if (codebaseField1 == null) { + codebaseField1 = new JTextField(); + codebaseField1.setHorizontalAlignment(SwingConstants.CENTER); + codebaseField1.setBounds(new java.awt.Rectangle(421,238,114,20)); + codebaseField1.setText("code/java"); + } + return codebaseField1; + } + + /** + * This method initializes jScrollPane + * + * @return javax.swing.JScrollPane + */ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setPreferredSize(new java.awt.Dimension(500,500)); + jScrollPane.setComponentOrientation(java.awt.ComponentOrientation.LEFT_TO_RIGHT); + jScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + jScrollPane.setName(""); + jScrollPane.setViewportView(getJContentPane3()); + } + return jScrollPane; + } + +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/PrefsTranslationsProvider.java b/simplCore/src/ecologylab/appframework/types/prefs/PrefsTranslationsProvider.java index 4c128fd7..ca588e48 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/PrefsTranslationsProvider.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/PrefsTranslationsProvider.java @@ -1,47 +1,47 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.generic.Debug; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.types.element.ElementTypeTranslationsProvider; - -/** - * Translations for the pref/meta_pref system. - * - * @author Cae - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class PrefsTranslationsProvider extends Debug -{ - /** - * Package name - */ - public static final String PREFS_TRANSLATIONS_NAME = "PREFS_TRANSLATIONS_NAME"; - - /** - * Additional classes needed to do Prefs translations. Most are provided by - * PrefSetBaseClassProvider. - */ - private static final Class[] translations = - { RangeState.class, - RangeIntState.class, RangeFloatState.class, - - Choice.class, ChoiceInt.class, ChoiceBoolean.class, ChoiceFloat.class }; - - public static final PrefsTranslationsProvider STATIC_INSTANCE = new PrefsTranslationsProvider(); - - private PrefsTranslationsProvider() - { - } - - /** - * Get the translation space - */ - public static SimplTypesScope get() - { - return SimplTypesScope.get(PREFS_TRANSLATIONS_NAME, ElementTypeTranslationsProvider.get(), - translations, PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses()); - } -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.generic.Debug; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.types.element.ElementTypeTranslationsProvider; + +/** + * Translations for the pref/meta_pref system. + * + * @author Cae + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class PrefsTranslationsProvider extends Debug +{ + /** + * Package name + */ + public static final String PREFS_TRANSLATIONS_NAME = "PREFS_TRANSLATIONS_NAME"; + + /** + * Additional classes needed to do Prefs translations. Most are provided by + * PrefSetBaseClassProvider. + */ + private static final Class[] translations = + { RangeState.class, + RangeIntState.class, RangeFloatState.class, + + Choice.class, ChoiceInt.class, ChoiceBoolean.class, ChoiceFloat.class }; + + public static final PrefsTranslationsProvider STATIC_INSTANCE = new PrefsTranslationsProvider(); + + private PrefsTranslationsProvider() + { + } + + /** + * Get the translation space + */ + public static SimplTypesScope get() + { + return SimplTypesScope.get(PREFS_TRANSLATIONS_NAME, ElementTypeTranslationsProvider.get(), + translations, PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses()); + } +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/RangeFloatState.java b/simplCore/src/ecologylab/appframework/types/prefs/RangeFloatState.java index c2d5a82e..1b400c5a 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/RangeFloatState.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/RangeFloatState.java @@ -1,77 +1,77 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author andruid - * - */ -@simpl_inherit -public class RangeFloatState extends ElementState /* RangeState */ -{ - /** - * Min value. - */ - @simpl_scalar float min; - /** - * Max value. - */ - @simpl_scalar float max; - - /** - * - */ - public RangeFloatState() - { - super(); - } - -/** - * Check to see that the newValue is within the range specifed by this. - * @param newValue - * @return - */ - protected boolean isWithinRange(Float newValue) - { - float value = newValue.floatValue(); - return (min <= value) && (value <= max); - } - - /** - * Get max value. - */ - public Float getMax() - { - return this.max; - } - - /** - * Get min value. - */ - public Float getMin() - { - return this.min; - } - - /** - * Set max value. - */ - public void setMax(Float newValue) - { - this.max = newValue; - } - - /** - * Set min value. - */ - public void setMin(Float newValue) - { - this.min = newValue; - } - -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author andruid + * + */ +@simpl_inherit +public class RangeFloatState extends ElementState /* RangeState */ +{ + /** + * Min value. + */ + @simpl_scalar float min; + /** + * Max value. + */ + @simpl_scalar float max; + + /** + * + */ + public RangeFloatState() + { + super(); + } + +/** + * Check to see that the newValue is within the range specifed by this. + * @param newValue + * @return + */ + protected boolean isWithinRange(Float newValue) + { + float value = newValue.floatValue(); + return (min <= value) && (value <= max); + } + + /** + * Get max value. + */ + public Float getMax() + { + return this.max; + } + + /** + * Get min value. + */ + public Float getMin() + { + return this.min; + } + + /** + * Set max value. + */ + public void setMax(Float newValue) + { + this.max = newValue; + } + + /** + * Set min value. + */ + public void setMin(Float newValue) + { + this.min = newValue; + } + +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/RangeIntState.java b/simplCore/src/ecologylab/appframework/types/prefs/RangeIntState.java index 1baabb35..bdb80e06 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/RangeIntState.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/RangeIntState.java @@ -1,77 +1,77 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author andruid - * - */ -@simpl_inherit -public class RangeIntState extends ElementState /* RangeState */ -{ - /** - * Min value. - */ - @simpl_scalar int min; - /** - * Max value. - */ - @simpl_scalar int max; - - /** - * - */ - public RangeIntState() - { - super(); - } - -/** - * Check to see that the newValue is within the range specifed by this. - * @param newValue - * @return - */ - protected boolean isWithinRange(Integer newValue) - { - int value = newValue.intValue(); - return (min <= value) && (value <= max); - } - - /** - * Get max value. - */ - public Integer getMax() - { - return this.max; - } - - /** - * Get min value. - */ - public Integer getMin() - { - return this.min; - } - - /** - * Set max value. - */ - public void setMax(Integer newValue) - { - this.max = newValue; - } - - /** - * Set min value. - */ - public void setMin(Integer newValue) - { - this.min = newValue; - } - -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author andruid + * + */ +@simpl_inherit +public class RangeIntState extends ElementState /* RangeState */ +{ + /** + * Min value. + */ + @simpl_scalar int min; + /** + * Max value. + */ + @simpl_scalar int max; + + /** + * + */ + public RangeIntState() + { + super(); + } + +/** + * Check to see that the newValue is within the range specifed by this. + * @param newValue + * @return + */ + protected boolean isWithinRange(Integer newValue) + { + int value = newValue.intValue(); + return (min <= value) && (value <= max); + } + + /** + * Get max value. + */ + public Integer getMax() + { + return this.max; + } + + /** + * Get min value. + */ + public Integer getMin() + { + return this.min; + } + + /** + * Set max value. + */ + public void setMax(Integer newValue) + { + this.max = newValue; + } + + /** + * Set min value. + */ + public void setMin(Integer newValue) + { + this.min = newValue; + } + +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/RangeState.java b/simplCore/src/ecologylab/appframework/types/prefs/RangeState.java index 351c8229..bca8a1fd 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/RangeState.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/RangeState.java @@ -1,43 +1,43 @@ -package ecologylab.appframework.types.prefs; - -import ecologylab.serialization.ElementState; - -abstract public class RangeState extends ElementState -{ - //@xml_attribute T min; - //@xml_attribute T max; - - public RangeState() - { - super(); - } - - /** - * Whether or not the value is in the range. - * @param newValue - */ - abstract protected boolean isWithinRange(T newValue); - /** - * Get the min of a choice. Type-specific. - */ - public abstract T getMin(); - - /** - * Set the min of a choice. Type-specific. - */ - public abstract void setMin(T newValue); - /** - * Get the max of a choice. Type-specific. - */ - public abstract T getMax(); - - /** - * Set the max of a choice. Type-specific. - */ - public abstract void setMax(T newValue); -/* protected boolean isWithinRange(T newValue) - { - return (newValue >= min) && (newValue <= max); - } - */ -} +package ecologylab.appframework.types.prefs; + +import ecologylab.serialization.ElementState; + +abstract public class RangeState extends ElementState +{ + //@xml_attribute T min; + //@xml_attribute T max; + + public RangeState() + { + super(); + } + + /** + * Whether or not the value is in the range. + * @param newValue + */ + abstract protected boolean isWithinRange(T newValue); + /** + * Get the min of a choice. Type-specific. + */ + public abstract T getMin(); + + /** + * Set the min of a choice. Type-specific. + */ + public abstract void setMin(T newValue); + /** + * Get the max of a choice. Type-specific. + */ + public abstract T getMax(); + + /** + * Set the max of a choice. Type-specific. + */ + public abstract void setMax(T newValue); +/* protected boolean isWithinRange(T newValue) + { + return (newValue >= min) && (newValue <= max); + } + */ +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/ValueChangedListener.java b/simplCore/src/ecologylab/appframework/types/prefs/ValueChangedListener.java index 85d174aa..5087bb0b 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/ValueChangedListener.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/ValueChangedListener.java @@ -1,6 +1,6 @@ -package ecologylab.appframework.types.prefs; - -public interface ValueChangedListener -{ - public void valueChanged(Pref pref); -} +package ecologylab.appframework.types.prefs; + +public interface ValueChangedListener +{ + public void valueChanged(Pref pref); +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/WidgetTypes.java b/simplCore/src/ecologylab/appframework/types/prefs/WidgetTypes.java index 195ba55e..eac28a3a 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/WidgetTypes.java +++ b/simplCore/src/ecologylab/appframework/types/prefs/WidgetTypes.java @@ -1,29 +1,29 @@ -package ecologylab.appframework.types.prefs; - -/** - * Types of graphical user interface components for interactive setting / - * editing Preference values. - * - * @author andruid - */ -public interface WidgetTypes -{ - public static final String TEXT_FIELD = "TEXT_FIELD"; - - public static final String RADIO_BUTTONS = "RADIO"; - - /** Not used. * */ - public static final String TEXT_AREA = "TEXT_AREA"; - - public static final String CHECK_BOX = "CHECK_BOX"; - - public static final String DROP_DOWN = "DROP_DOWN"; - - public static final String COLOR_CHOOSER = "COLOR_CHOOSER"; - - public static final String FILE_CHOOSER = "FILE_CHOOSER"; - - public static final String SLIDER = "SLIDER"; - - public static final String SPINNER = "SPINNER"; -} +package ecologylab.appframework.types.prefs; + +/** + * Types of graphical user interface components for interactive setting / + * editing Preference values. + * + * @author andruid + */ +public interface WidgetTypes +{ + public static final String TEXT_FIELD = "TEXT_FIELD"; + + public static final String RADIO_BUTTONS = "RADIO"; + + /** Not used. * */ + public static final String TEXT_AREA = "TEXT_AREA"; + + public static final String CHECK_BOX = "CHECK_BOX"; + + public static final String DROP_DOWN = "DROP_DOWN"; + + public static final String COLOR_CHOOSER = "COLOR_CHOOSER"; + + public static final String FILE_CHOOSER = "FILE_CHOOSER"; + + public static final String SLIDER = "SLIDER"; + + public static final String SPINNER = "SPINNER"; +} diff --git a/simplCore/src/ecologylab/appframework/types/prefs/package.html b/simplCore/src/ecologylab/appframework/types/prefs/package.html index 0b61dd68..a8e78726 100644 --- a/simplCore/src/ecologylab/appframework/types/prefs/package.html +++ b/simplCore/src/ecologylab/appframework/types/prefs/package.html @@ -1,4 +1,4 @@ - -Type declarations for preferences, in the Interface Ecology Lab Application -Development Framework. - + +Type declarations for preferences, in the Interface Ecology Lab Application +Development Framework. + diff --git a/simplCore/src/ecologylab/collections/AbstractSetElement.java b/simplCore/src/ecologylab/collections/AbstractSetElement.java index 97be442e..8e41c3ba 100644 --- a/simplCore/src/ecologylab/collections/AbstractSetElement.java +++ b/simplCore/src/ecologylab/collections/AbstractSetElement.java @@ -1,16 +1,16 @@ -package ecologylab.collections; - -public interface AbstractSetElement -{ - public void delete(); - - public void addSet(WeightSet s); - public void removeSet(WeightSet s); - public boolean isInSet(); - - public void deleteHook(); - public void insertHook(); - - public void recycle(boolean allContents); - public boolean recycled(); -} +package ecologylab.collections; + +public interface AbstractSetElement +{ + public void delete(); + + public void addSet(WeightSet s); + public void removeSet(WeightSet s); + public boolean isInSet(); + + public void deleteHook(); + public void insertHook(); + + public void recycle(boolean allContents); + public boolean recycled(); +} diff --git a/simplCore/src/ecologylab/collections/ArrayListFloatSet.java b/simplCore/src/ecologylab/collections/ArrayListFloatSet.java index 3fbe86c7..2423044d 100644 --- a/simplCore/src/ecologylab/collections/ArrayListFloatSet.java +++ b/simplCore/src/ecologylab/collections/ArrayListFloatSet.java @@ -1,92 +1,92 @@ -/* - * Created on Jun 26, 2005 - */ -package ecologylab.collections; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * A set of FloatSetElements, that uses ArrayList as the storage medium. - * - * @author andruid - */ -public class ArrayListFloatSet -extends ArrayList -implements BasicFloatSet -{ - /** - * - */ - public ArrayListFloatSet() - { - super(); - } - - /** - * @param arg0 - */ - public ArrayListFloatSet(int arg0) - { - super(arg0); - } - - /** - * @param arg0 - */ - public ArrayListFloatSet(Collection arg0) - { - super(arg0); - } - - /** - * Delete an element from the set. - * If they are relevant, perhaps recompute internal structures, such as - * incremental sums, or tree/heap balancing, depending on the value of the - * recompute parameter. - * - * @param el The FloatSetElement element to delete. - * @param recompute -1 for absolutely no recompute. - * 0 for recompute upwards from el. - * 1 for recompute all. - **/ - @Override - public void delete(T el, int recompute) - { - remove(el); - } - public void insert(T element) - { - element.setSet(this); - int index = size(); - add(element); - element.setIndex(index); - } - - /** - * Get the ith element in the set. - * - * @param i - * @return - */ - public T getElement(int i) - { - return super.get(i); - } - /** - * Get the last element in the set, or null if the set is empty. - * - * @return - */ - @Override -public T lastElement() - { - int size = size(); - return (size == 0) ? null : get(size - 1); - } - - @Override - public void decrement(T el) - { - } -} +/* + * Created on Jun 26, 2005 + */ +package ecologylab.collections; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * A set of FloatSetElements, that uses ArrayList as the storage medium. + * + * @author andruid + */ +public class ArrayListFloatSet +extends ArrayList +implements BasicFloatSet +{ + /** + * + */ + public ArrayListFloatSet() + { + super(); + } + + /** + * @param arg0 + */ + public ArrayListFloatSet(int arg0) + { + super(arg0); + } + + /** + * @param arg0 + */ + public ArrayListFloatSet(Collection arg0) + { + super(arg0); + } + + /** + * Delete an element from the set. + * If they are relevant, perhaps recompute internal structures, such as + * incremental sums, or tree/heap balancing, depending on the value of the + * recompute parameter. + * + * @param el The FloatSetElement element to delete. + * @param recompute -1 for absolutely no recompute. + * 0 for recompute upwards from el. + * 1 for recompute all. + **/ + @Override + public void delete(T el, int recompute) + { + remove(el); + } + public void insert(T element) + { + element.setSet(this); + int index = size(); + add(element); + element.setIndex(index); + } + + /** + * Get the ith element in the set. + * + * @param i + * @return + */ + public T getElement(int i) + { + return super.get(i); + } + /** + * Get the last element in the set, or null if the set is empty. + * + * @return + */ + @Override +public T lastElement() + { + int size = size(); + return (size == 0) ? null : get(size - 1); + } + + @Override + public void decrement(T el) + { + } +} diff --git a/simplCore/src/ecologylab/collections/ArrayListInBounds.java b/simplCore/src/ecologylab/collections/ArrayListInBounds.java index 5edc0d39..2bc074fe 100644 --- a/simplCore/src/ecologylab/collections/ArrayListInBounds.java +++ b/simplCore/src/ecologylab/collections/ArrayListInBounds.java @@ -1,29 +1,29 @@ -/** - * - */ -package ecologylab.collections; - -import java.util.ArrayList; - -/** - * An ArrayList that returns null if get(int)'ing an element that does not exist. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class ArrayListInBounds extends ArrayList -{ - private static final long serialVersionUID = -4733082961336679335L; - - /** - * @see java.util.ArrayList#get(int) - */ - @Override - public T get(int index) - { - if (index >= super.size() || index < 0) - return null; - - return super.get(index); - } - -} +/** + * + */ +package ecologylab.collections; + +import java.util.ArrayList; + +/** + * An ArrayList that returns null if get(int)'ing an element that does not exist. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class ArrayListInBounds extends ArrayList +{ + private static final long serialVersionUID = -4733082961336679335L; + + /** + * @see java.util.ArrayList#get(int) + */ + @Override + public T get(int index) + { + if (index >= super.size() || index < 0) + return null; + + return super.get(index); + } + +} diff --git a/simplCore/src/ecologylab/collections/ArrayListLA.java b/simplCore/src/ecologylab/collections/ArrayListLA.java index 7ba410d2..87478e3a 100644 --- a/simplCore/src/ecologylab/collections/ArrayListLA.java +++ b/simplCore/src/ecologylab/collections/ArrayListLA.java @@ -1,27 +1,27 @@ -package ecologylab.collections; - -import java.util.ArrayList; -import java.util.Collection; - -public class ArrayListLA extends ArrayList -implements LinearAccess -{ - - public ArrayListLA() - { - // TODO Auto-generated constructor stub - } - - public ArrayListLA(int initialCapacity) - { - super(initialCapacity); - // TODO Auto-generated constructor stub - } - - public ArrayListLA(Collection c) - { - super(c); - // TODO Auto-generated constructor stub - } - -} +package ecologylab.collections; + +import java.util.ArrayList; +import java.util.Collection; + +public class ArrayListLA extends ArrayList +implements LinearAccess +{ + + public ArrayListLA() + { + // TODO Auto-generated constructor stub + } + + public ArrayListLA(int initialCapacity) + { + super(initialCapacity); + // TODO Auto-generated constructor stub + } + + public ArrayListLA(Collection c) + { + super(c); + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/collections/BasicFloatSet.java b/simplCore/src/ecologylab/collections/BasicFloatSet.java index 77bf70f9..30d0064b 100644 --- a/simplCore/src/ecologylab/collections/BasicFloatSet.java +++ b/simplCore/src/ecologylab/collections/BasicFloatSet.java @@ -1,68 +1,68 @@ -package ecologylab.collections; - -/** - * Minimal set of functions needed for collections of FloatSetElements. - * - * @author andruid - */ -public interface BasicFloatSet -extends LinearAccess -{ - /** - * A flag that may be passed to the delete method. - * Indicates minimize recomputation. Be as expedient as possible. - */ - public static final int NO_RECOMPUTE = -1; - - /** - * A flag that may be passed to the delete method. - * Indicates do recompute partially, from this element only, - * to maintain the structural integrity of the set. - */ - public static final int PARTIAL_RECOMPUTE = 0; - - /** - * A flag that may be passed to the delete method. - * Indicates do whatever is necessary to maintain the structural integrity - * of the set. - */ - public static final int RECOMPUTE_ALL = 1; - - /** - * Delete an element from the set. - * If they are relevant, perhaps recompute internal structures, such as - * incremental sums, or tree/heap balancing, depending on the value of the - * recompute parameter. - * - * @param el The FloatSetElement element to delete. - * @param recompute -1 for absolutely no recompute. - * 0 for recompute upwards from el. - * 1 for recompute all. - **/ - public void delete(E el, int recompute); - - /** - * Get the ith element in the set. - * - * @param i - * @return - */ - @Override - public E get(int i); - - /** - * Get the last element in the set, or null if the set is empty. - * - * @return - */ - public E lastElement(); - - /** - * Check to see if the set has any elements. - * @return - */ - @Override - public boolean isEmpty(); - - public void decrement(E el); -} +package ecologylab.collections; + +/** + * Minimal set of functions needed for collections of FloatSetElements. + * + * @author andruid + */ +public interface BasicFloatSet +extends LinearAccess +{ + /** + * A flag that may be passed to the delete method. + * Indicates minimize recomputation. Be as expedient as possible. + */ + public static final int NO_RECOMPUTE = -1; + + /** + * A flag that may be passed to the delete method. + * Indicates do recompute partially, from this element only, + * to maintain the structural integrity of the set. + */ + public static final int PARTIAL_RECOMPUTE = 0; + + /** + * A flag that may be passed to the delete method. + * Indicates do whatever is necessary to maintain the structural integrity + * of the set. + */ + public static final int RECOMPUTE_ALL = 1; + + /** + * Delete an element from the set. + * If they are relevant, perhaps recompute internal structures, such as + * incremental sums, or tree/heap balancing, depending on the value of the + * recompute parameter. + * + * @param el The FloatSetElement element to delete. + * @param recompute -1 for absolutely no recompute. + * 0 for recompute upwards from el. + * 1 for recompute all. + **/ + public void delete(E el, int recompute); + + /** + * Get the ith element in the set. + * + * @param i + * @return + */ + @Override + public E get(int i); + + /** + * Get the last element in the set, or null if the set is empty. + * + * @return + */ + public E lastElement(); + + /** + * Check to see if the set has any elements. + * @return + */ + @Override + public boolean isEmpty(); + + public void decrement(E el); +} diff --git a/simplCore/src/ecologylab/collections/ChildPrefixMap.java b/simplCore/src/ecologylab/collections/ChildPrefixMap.java index 6bebe4fa..6686bbd7 100644 --- a/simplCore/src/ecologylab/collections/ChildPrefixMap.java +++ b/simplCore/src/ecologylab/collections/ChildPrefixMap.java @@ -1,106 +1,106 @@ -/** - * - */ -package ecologylab.collections; - -import java.util.HashMap; -import java.util.Map; - -/** - * Mostly extends HashMap - * - * However, for put, checks to see if String key is WILDCARD. - * If so, sets special wildcardMatch slot instead of adding to HashMap. - *

- * Likewise, for get(), if a specific match does not work, chekcs to see if there is a wildcardMatch. - * If there is one, it will be returned. - * - * @author andruid - * - */ -public class ChildPrefixMap extends HashMap -{ - private PrefixPhrase wildcardMatch; - - public static final String WILDCARD = "*"; - - /** - * - */ - public ChildPrefixMap() - { - // TODO Auto-generated constructor stub - } - - /** - * @param initialCapacity - */ - public ChildPrefixMap(int initialCapacity) - { - super(initialCapacity); - // TODO Auto-generated constructor stub - } - - /** - * @param m - */ - public ChildPrefixMap(Map m) - { - super(m); - // TODO Auto-generated constructor stub - } - - /** - * @param initialCapacity - * @param loadFactor - */ - public ChildPrefixMap(int initialCapacity, float loadFactor) - { - super(initialCapacity, loadFactor); - // TODO Auto-generated constructor stub - } - /** - * For put, checks to see if String key is WILDCARD. - * If so, sets special wildcardMatch slot instead of adding to HashMap. - */ - @Override - public PrefixPhrase put(String key, PrefixPhrase value) - { - if (WILDCARD.equals(key)) - { - PrefixPhrase result = wildcardMatch; - wildcardMatch = value; - return result; - } - return super.put(key, value); - } - /** - * For get(), if a specific match does not work, check to see if there is a wildcardMatch. - * If there is one, it will be returned. - */ - @Override - public PrefixPhrase get(Object key) - { - PrefixPhrase result = super.get(key); - return (result != null) ? result : wildcardMatch; - } - - public PrefixPhrase getWildcardMatch() - { - return wildcardMatch; - } - - public void setWildcardMatch(PrefixPhrase wildcardMatch) - { - this.wildcardMatch = wildcardMatch; - } - - @Override - public int size() - { - int result = super.size(); - if (wildcardMatch != null) - result++; - return result; - } -} +/** + * + */ +package ecologylab.collections; + +import java.util.HashMap; +import java.util.Map; + +/** + * Mostly extends HashMap + * + * However, for put, checks to see if String key is WILDCARD. + * If so, sets special wildcardMatch slot instead of adding to HashMap. + *

+ * Likewise, for get(), if a specific match does not work, chekcs to see if there is a wildcardMatch. + * If there is one, it will be returned. + * + * @author andruid + * + */ +public class ChildPrefixMap extends HashMap +{ + private PrefixPhrase wildcardMatch; + + public static final String WILDCARD = "*"; + + /** + * + */ + public ChildPrefixMap() + { + // TODO Auto-generated constructor stub + } + + /** + * @param initialCapacity + */ + public ChildPrefixMap(int initialCapacity) + { + super(initialCapacity); + // TODO Auto-generated constructor stub + } + + /** + * @param m + */ + public ChildPrefixMap(Map m) + { + super(m); + // TODO Auto-generated constructor stub + } + + /** + * @param initialCapacity + * @param loadFactor + */ + public ChildPrefixMap(int initialCapacity, float loadFactor) + { + super(initialCapacity, loadFactor); + // TODO Auto-generated constructor stub + } + /** + * For put, checks to see if String key is WILDCARD. + * If so, sets special wildcardMatch slot instead of adding to HashMap. + */ + @Override + public PrefixPhrase put(String key, PrefixPhrase value) + { + if (WILDCARD.equals(key)) + { + PrefixPhrase result = wildcardMatch; + wildcardMatch = value; + return result; + } + return super.put(key, value); + } + /** + * For get(), if a specific match does not work, check to see if there is a wildcardMatch. + * If there is one, it will be returned. + */ + @Override + public PrefixPhrase get(Object key) + { + PrefixPhrase result = super.get(key); + return (result != null) ? result : wildcardMatch; + } + + public PrefixPhrase getWildcardMatch() + { + return wildcardMatch; + } + + public void setWildcardMatch(PrefixPhrase wildcardMatch) + { + this.wildcardMatch = wildcardMatch; + } + + @Override + public int size() + { + int result = super.size(); + if (wildcardMatch != null) + result++; + return result; + } +} diff --git a/simplCore/src/ecologylab/collections/CollectionTools.java b/simplCore/src/ecologylab/collections/CollectionTools.java index 9c11ae6a..5823ab6d 100644 --- a/simplCore/src/ecologylab/collections/CollectionTools.java +++ b/simplCore/src/ecologylab/collections/CollectionTools.java @@ -1,157 +1,157 @@ -/** - * - */ -package ecologylab.collections; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import ecologylab.generic.Debug; -import ecologylab.generic.IntSlot; -import ecologylab.generic.StringTools; - -/** - * Convenience methods for creating and manipulating collections. - * - * @author andruid - * - */ -public class CollectionTools extends Debug -{ - - /** - * Create a HashMap, and populate with entries from the passed in array of Strings. The key and - * value will be the same for each entry. - * - * @param strings - * @return - */ - public static final HashMap buildHashMapFromStrings(String[] strings) - { - HashMap hashMap = new HashMap(strings.length); - buildMapFromStrings(hashMap, strings); - return hashMap; - } - - /** - * Create a HashSet, and populate with entries from the passed in array of Strings. - * - * @param strings - * @return - */ - public static final HashSet buildHashSetFromStrings(String[] strings) - { - HashSet result = new HashSet(strings.length); - buildSetFromStrings(result, strings); - return result; - } - - /** - * Create a HashMap, and populate with entries from the passed in array of Strings. But only use - * Strings that are lower case; other entries in the array are ignored. The key and value will be - * the same for each entry. - * - * @param strings - * @return - */ - public static final HashMap buildHashMapFromLCStrings(String[] strings) - { - HashMap hashMap = new HashMap(strings.length); - buildMapFromLCStrings(hashMap, strings); - return hashMap; - } - - /** - * Create a HashMap, and popuplate with entries from the passed in array of key value pairs. - * - * @param entries - * @return - */ - public static HashMap buildHashMap(T[][] entries) - { - HashMap hashMap = new HashMap(entries.length); - buildMap(hashMap, entries); - return hashMap; - } - - /** - * Populate a HashMap from the supplied array of Strings. The key and value will be the same for - * each entry. - * - * @param map - * @param strings - */ - public static final void buildMapFromStrings(Map map, String[] strings) - { - for (String thatString: strings) - map.put(thatString, thatString); - } - - /** - * Populate a HashMap from the supplied array of Strings. The key and value will be the same for - * each entry. - * - * @param map - * @param strings - */ - public static final void buildSetFromStrings(Set set, String[] strings) - { - for (String thatString: strings) - set.add(thatString); - } - - /** - * Populate a HashMap from the supplied array of Strings. But only use Strings that are lower - * case; other entries in the array are ignored. The key and value will be the same for each - * entry. - * - * @param map - * @param strings - */ - public static final void buildMapFromLCStrings(Map map, String[] strings) - { - for (String thatString: strings) - { - if (StringTools.isLowerCase(thatString)) - map.put(thatString, thatString); - } - } - - public static void buildMap(Map map, T[][] entries) - { - for (int i = 0; i < entries.length; i++) - { - T[] thatEntry = entries[i]; - T thatKey = thatEntry[0]; - T thatValue = thatEntry[1]; - map.put(thatKey, thatValue); - } - } - - // The keys come from the String[], the values are corresponding number start with 0 - public static final HashMap buildNumberHashMapFromStrings(String[] strings) - { - HashMap hashMap = new HashMap(strings.length); - buildNumberMapFromStrings(hashMap, strings); - return hashMap; - } - - // The keys come from the String[], the values are corresponding number start with 0 - public static final void buildNumberMapFromStrings(Map map, String[] strings) - { - for (int i = 0; i < strings.length; i++) - { - String thatString = strings[i]; - Integer integer = new Integer(i); - map.put(thatString, integer); - } - } - - public static final void stringIntMapEntry(Map map, String string, int integer) - { - map.put(string, new IntSlot(integer)); - } - -} +/** + * + */ +package ecologylab.collections; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import ecologylab.generic.Debug; +import ecologylab.generic.IntSlot; +import ecologylab.generic.StringTools; + +/** + * Convenience methods for creating and manipulating collections. + * + * @author andruid + * + */ +public class CollectionTools extends Debug +{ + + /** + * Create a HashMap, and populate with entries from the passed in array of Strings. The key and + * value will be the same for each entry. + * + * @param strings + * @return + */ + public static final HashMap buildHashMapFromStrings(String[] strings) + { + HashMap hashMap = new HashMap(strings.length); + buildMapFromStrings(hashMap, strings); + return hashMap; + } + + /** + * Create a HashSet, and populate with entries from the passed in array of Strings. + * + * @param strings + * @return + */ + public static final HashSet buildHashSetFromStrings(String[] strings) + { + HashSet result = new HashSet(strings.length); + buildSetFromStrings(result, strings); + return result; + } + + /** + * Create a HashMap, and populate with entries from the passed in array of Strings. But only use + * Strings that are lower case; other entries in the array are ignored. The key and value will be + * the same for each entry. + * + * @param strings + * @return + */ + public static final HashMap buildHashMapFromLCStrings(String[] strings) + { + HashMap hashMap = new HashMap(strings.length); + buildMapFromLCStrings(hashMap, strings); + return hashMap; + } + + /** + * Create a HashMap, and popuplate with entries from the passed in array of key value pairs. + * + * @param entries + * @return + */ + public static HashMap buildHashMap(T[][] entries) + { + HashMap hashMap = new HashMap(entries.length); + buildMap(hashMap, entries); + return hashMap; + } + + /** + * Populate a HashMap from the supplied array of Strings. The key and value will be the same for + * each entry. + * + * @param map + * @param strings + */ + public static final void buildMapFromStrings(Map map, String[] strings) + { + for (String thatString: strings) + map.put(thatString, thatString); + } + + /** + * Populate a HashMap from the supplied array of Strings. The key and value will be the same for + * each entry. + * + * @param map + * @param strings + */ + public static final void buildSetFromStrings(Set set, String[] strings) + { + for (String thatString: strings) + set.add(thatString); + } + + /** + * Populate a HashMap from the supplied array of Strings. But only use Strings that are lower + * case; other entries in the array are ignored. The key and value will be the same for each + * entry. + * + * @param map + * @param strings + */ + public static final void buildMapFromLCStrings(Map map, String[] strings) + { + for (String thatString: strings) + { + if (StringTools.isLowerCase(thatString)) + map.put(thatString, thatString); + } + } + + public static void buildMap(Map map, T[][] entries) + { + for (int i = 0; i < entries.length; i++) + { + T[] thatEntry = entries[i]; + T thatKey = thatEntry[0]; + T thatValue = thatEntry[1]; + map.put(thatKey, thatValue); + } + } + + // The keys come from the String[], the values are corresponding number start with 0 + public static final HashMap buildNumberHashMapFromStrings(String[] strings) + { + HashMap hashMap = new HashMap(strings.length); + buildNumberMapFromStrings(hashMap, strings); + return hashMap; + } + + // The keys come from the String[], the values are corresponding number start with 0 + public static final void buildNumberMapFromStrings(Map map, String[] strings) + { + for (int i = 0; i < strings.length; i++) + { + String thatString = strings[i]; + Integer integer = new Integer(i); + map.put(thatString, integer); + } + } + + public static final void stringIntMapEntry(Map map, String string, int integer) + { + map.put(string, new IntSlot(integer)); + } + +} diff --git a/simplCore/src/ecologylab/collections/ConcurrentHashSet.java b/simplCore/src/ecologylab/collections/ConcurrentHashSet.java index e7eacb45..77f41ea2 100644 --- a/simplCore/src/ecologylab/collections/ConcurrentHashSet.java +++ b/simplCore/src/ecologylab/collections/ConcurrentHashSet.java @@ -1,78 +1,78 @@ -/** - * - */ -package ecologylab.collections; - -import java.util.AbstractSet; -import java.util.Iterator; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Low locking ConcurrentHashSet uses ConcurrentHashMap to lock only when add actually adds. - * - * @author andruid - */ -public class ConcurrentHashSet extends AbstractSet -{ - private ConcurrentHashMap map; - - public ConcurrentHashSet() - { - map = new ConcurrentHashMap(); - } - - public ConcurrentHashSet(int capacity) - { - map = new ConcurrentHashMap(capacity); - } - - public ConcurrentHashSet(Set set) - { - for (E element: set) - map.put(element, element); - } - /** - * Add element to set if it wasn't there already. - * - * @param element Element to test for membership and add if it was absent. - * - * @return true if the set changed, that is, if the element was new. - */ - @Override - public boolean add(E element) - { - E fromCollection = map.putIfAbsent(element, element); - return fromCollection == null; // previous value is null means that the collection changed. - } - - @Override - public void clear() - { - map.clear(); - } - - @Override - public boolean contains(Object obj) - { - return map.containsKey(obj); - } - - @Override - public Iterator iterator() - { - return map.keySet().iterator(); - } - - @Override - public boolean remove(Object obj) - { - return map.remove(obj) != null; - } - - @Override - public int size() - { - return map.size(); - } -} +/** + * + */ +package ecologylab.collections; + +import java.util.AbstractSet; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Low locking ConcurrentHashSet uses ConcurrentHashMap to lock only when add actually adds. + * + * @author andruid + */ +public class ConcurrentHashSet extends AbstractSet +{ + private ConcurrentHashMap map; + + public ConcurrentHashSet() + { + map = new ConcurrentHashMap(); + } + + public ConcurrentHashSet(int capacity) + { + map = new ConcurrentHashMap(capacity); + } + + public ConcurrentHashSet(Set set) + { + for (E element: set) + map.put(element, element); + } + /** + * Add element to set if it wasn't there already. + * + * @param element Element to test for membership and add if it was absent. + * + * @return true if the set changed, that is, if the element was new. + */ + @Override + public boolean add(E element) + { + E fromCollection = map.putIfAbsent(element, element); + return fromCollection == null; // previous value is null means that the collection changed. + } + + @Override + public void clear() + { + map.clear(); + } + + @Override + public boolean contains(Object obj) + { + return map.containsKey(obj); + } + + @Override + public Iterator iterator() + { + return map.keySet().iterator(); + } + + @Override + public boolean remove(Object obj) + { + return map.remove(obj) != null; + } + + @Override + public int size() + { + return map.size(); + } +} diff --git a/simplCore/src/ecologylab/collections/DLL.java b/simplCore/src/ecologylab/collections/DLL.java index 59376556..e4de91f7 100644 --- a/simplCore/src/ecologylab/collections/DLL.java +++ b/simplCore/src/ecologylab/collections/DLL.java @@ -1,267 +1,267 @@ -/* - * Copyright 1996-2002 by Andruid Kerne. All rights reserved. - * CONFIDENTIAL. Use is subject to license terms. - */ -package ecologylab.collections; -//import java.awt.Toolkit; -import java.util.Iterator; - -import ecologylab.generic.Debug; - -/** - * Doubly linked list of GUI components. Maintains family tree. - */ -public class DLL -extends Debug -implements Iterable -{ - private DLL prevSib; - private DLL nextSib; - - private T object; - - public DLL(T objectArg) - { - object = objectArg; - } -/** - * Add sibs after ourself. - */ - public synchronized void addAfter(DLL sibs) - { - sibs.setNext(nextSib); - addToEnd(sibs); - } - - /** - * Insert sibs before ourself. - */ - public synchronized void insertBefore(DLL sibs) - { - sibs.setPrev(prevSib); - if (prevSib != null) - prevSib.setNext(sibs); - sibs.setNext(this); - prevSib = sibs; - } -/** - * Add sibs to the end of this. - * - * @param sibs DLL for object added to the end of this. - */ - public void addToEnd(DLL sibs) - { - if (sibs == this) - { - debug("ERROR!!!! adding to end of self!!!!"); - //Toolkit.getDefaultToolkit().beep(); - Thread.dumpStack(); - } - - nextSib = sibs; // ??? should this be setNext(sibs) -- sync -// setNext(sibs); - sibs.setPrev(this); - } -/** - * Prepend sibs to the start of this. - * - * @param sibs DLL for object added before this. - */ - public void addAtBeginning(DLL sibs) - { - if (sibs == this) - { - debug("ERROR!!!! adding to end of self!!!!"); -// /Toolkit.getDefaultToolkit().beep(); - Thread.dumpStack(); - } - - prevSib = sibs; // ??? should this be setNext(sibs) -- sync -// setNext(sibs); - sibs.setNext(this); - } -/** - * Remove I and I from the dll of sibs. - */ - public synchronized void remove() - { - if (nextSib != null) - nextSib.setPrev(prevSib); - if (prevSib != null) - prevSib.setNext(nextSib); - prevSib = null; - nextSib = null; - //FIXME -- uncomment this out! -// object = null; // encourage gc ?? -- why is this commented out??? andruid 2/10/08 - } -/** - * Remove the relations of this node, while it is being manipulated in - * the midst of mergeSort(). - */ - public void clear() - { - prevSib = null; - nextSib = null; -// remove(); - object = null; - } -/** - * Remove the relations of this node, while it is being deleted. - */ - public void clearStronger() - { - remove(); - object = null; - } -/** - * Remove the relations of this node, while it is being rebuilt, and - * its associations are meaningless. - */ - public void clearRelations() - { - prevSib = null; - nextSib = null; - } -/** - * Not usually for public consumption. Only available for special sorts. - * With a getKey interface, the sort could be brought here, which will - * be better oo design. - */ - public synchronized void setNext(DLL next) - { - nextSib = next; - } - public synchronized void setPrev(DLL prev) - { - prevSib = prev; - } - public T getThis() - { - return object; - } - public synchronized T getNext() - { - return (nextSib == null) ? null : nextSib.object; - } - public synchronized T getPrev() - { - return (prevSib == null) ? null : prevSib.object; - } - public DLL prev() - { - return prevSib; - } - public DLL next() - { - return nextSib; - } - public DLL mergeSortDescending(MergeD mergeD, DLL zSibs) - { - DLL c = this; - int n = 1; - DLL head = new DLL(null); - head.setNext(c); - DLL a; - do - { - DLL todo = head.next(); - c = head; - int toMove = n - 1; -// System.out.println(""); -// visualize.CollageElement.printPieces(c.next(), zSibs); -// System.out.println("start inner loop moving " + toMove); - do - { - // merge lists of size n - DLL t = todo; - a = t; - for (int i=1; i<=toMove; i++) - t = t.next(); - DLL b = t.next(); - t.setNext(zSibs); - t = b; - for (int i=1; i<=toMove; i++) - t = t.next(); - todo = t.next(); - t.setNext(zSibs); -// System.out.println("mergeDescending(a: "); -// visualize.CollageElement.printPieces(a, zSibs); -// System.out.println("mergeDescending(b: "); -// visualize.CollageElement.printPieces(b, zSibs); - c.setNext(mergeD.mergeDescending(a,b)); -// System.out.println("returns: "); -// visualize.CollageElement.printPieces(c.next(), zSibs); - int twoN = n + n; - for (int i=1; i<=twoN; i++) - c = c.next(); - } while (todo != zSibs); - n += n; - } while (a != head.next()); - - DLL something = head; - DLL prev = something; - while (something != null) { - something = something.next(); - if (something == prev) - prev.setNext(null); - prev = something; - } - - return head.next(); - } - - /** - * @param object the object to set - */ - public void setObject(T object) - { - this.object = object; - } - - /** - * Create an {@code Iterator} object for this {@code DLL}. - * - * @return an {@code Iterator} object for iterating over all elements in this {@code DLL}. - */ - @Override -public Iterator iterator() - { - return new DLLIterator(); - } - - /** - * Iterator class for building an iterator object out of the DLL. Uses current - * DLL structure for iteration, starting at the DLL object that instantiates it. - * - */ - private class DLLIterator implements Iterator - { - DLL currentNode = DLL.this; - DLL firstObject = DLL.this; - boolean stop = false; - - @Override - public boolean hasNext() - { - return !stop && (currentNode != null && currentNode.object != null); - } - - @Override - public T next() - { - T currentObject = currentNode.object; - currentNode = currentNode.next(); - if (currentNode == firstObject) - stop = true; - - return currentObject; - } - - @Override - public void remove() - { - // optional method that is not needed in our case. - } - - } -} +/* + * Copyright 1996-2002 by Andruid Kerne. All rights reserved. + * CONFIDENTIAL. Use is subject to license terms. + */ +package ecologylab.collections; +//import java.awt.Toolkit; +import java.util.Iterator; + +import ecologylab.generic.Debug; + +/** + * Doubly linked list of GUI components. Maintains family tree. + */ +public class DLL +extends Debug +implements Iterable +{ + private DLL prevSib; + private DLL nextSib; + + private T object; + + public DLL(T objectArg) + { + object = objectArg; + } +/** + * Add sibs after ourself. + */ + public synchronized void addAfter(DLL sibs) + { + sibs.setNext(nextSib); + addToEnd(sibs); + } + + /** + * Insert sibs before ourself. + */ + public synchronized void insertBefore(DLL sibs) + { + sibs.setPrev(prevSib); + if (prevSib != null) + prevSib.setNext(sibs); + sibs.setNext(this); + prevSib = sibs; + } +/** + * Add sibs to the end of this. + * + * @param sibs DLL for object added to the end of this. + */ + public void addToEnd(DLL sibs) + { + if (sibs == this) + { + debug("ERROR!!!! adding to end of self!!!!"); + //Toolkit.getDefaultToolkit().beep(); + Thread.dumpStack(); + } + + nextSib = sibs; // ??? should this be setNext(sibs) -- sync +// setNext(sibs); + sibs.setPrev(this); + } +/** + * Prepend sibs to the start of this. + * + * @param sibs DLL for object added before this. + */ + public void addAtBeginning(DLL sibs) + { + if (sibs == this) + { + debug("ERROR!!!! adding to end of self!!!!"); +// /Toolkit.getDefaultToolkit().beep(); + Thread.dumpStack(); + } + + prevSib = sibs; // ??? should this be setNext(sibs) -- sync +// setNext(sibs); + sibs.setNext(this); + } +/** + * Remove I and I from the dll of sibs. + */ + public synchronized void remove() + { + if (nextSib != null) + nextSib.setPrev(prevSib); + if (prevSib != null) + prevSib.setNext(nextSib); + prevSib = null; + nextSib = null; + //FIXME -- uncomment this out! +// object = null; // encourage gc ?? -- why is this commented out??? andruid 2/10/08 + } +/** + * Remove the relations of this node, while it is being manipulated in + * the midst of mergeSort(). + */ + public void clear() + { + prevSib = null; + nextSib = null; +// remove(); + object = null; + } +/** + * Remove the relations of this node, while it is being deleted. + */ + public void clearStronger() + { + remove(); + object = null; + } +/** + * Remove the relations of this node, while it is being rebuilt, and + * its associations are meaningless. + */ + public void clearRelations() + { + prevSib = null; + nextSib = null; + } +/** + * Not usually for public consumption. Only available for special sorts. + * With a getKey interface, the sort could be brought here, which will + * be better oo design. + */ + public synchronized void setNext(DLL next) + { + nextSib = next; + } + public synchronized void setPrev(DLL prev) + { + prevSib = prev; + } + public T getThis() + { + return object; + } + public synchronized T getNext() + { + return (nextSib == null) ? null : nextSib.object; + } + public synchronized T getPrev() + { + return (prevSib == null) ? null : prevSib.object; + } + public DLL prev() + { + return prevSib; + } + public DLL next() + { + return nextSib; + } + public DLL mergeSortDescending(MergeD mergeD, DLL zSibs) + { + DLL c = this; + int n = 1; + DLL head = new DLL(null); + head.setNext(c); + DLL a; + do + { + DLL todo = head.next(); + c = head; + int toMove = n - 1; +// System.out.println(""); +// visualize.CollageElement.printPieces(c.next(), zSibs); +// System.out.println("start inner loop moving " + toMove); + do + { + // merge lists of size n + DLL t = todo; + a = t; + for (int i=1; i<=toMove; i++) + t = t.next(); + DLL b = t.next(); + t.setNext(zSibs); + t = b; + for (int i=1; i<=toMove; i++) + t = t.next(); + todo = t.next(); + t.setNext(zSibs); +// System.out.println("mergeDescending(a: "); +// visualize.CollageElement.printPieces(a, zSibs); +// System.out.println("mergeDescending(b: "); +// visualize.CollageElement.printPieces(b, zSibs); + c.setNext(mergeD.mergeDescending(a,b)); +// System.out.println("returns: "); +// visualize.CollageElement.printPieces(c.next(), zSibs); + int twoN = n + n; + for (int i=1; i<=twoN; i++) + c = c.next(); + } while (todo != zSibs); + n += n; + } while (a != head.next()); + + DLL something = head; + DLL prev = something; + while (something != null) { + something = something.next(); + if (something == prev) + prev.setNext(null); + prev = something; + } + + return head.next(); + } + + /** + * @param object the object to set + */ + public void setObject(T object) + { + this.object = object; + } + + /** + * Create an {@code Iterator} object for this {@code DLL}. + * + * @return an {@code Iterator} object for iterating over all elements in this {@code DLL}. + */ + @Override +public Iterator iterator() + { + return new DLLIterator(); + } + + /** + * Iterator class for building an iterator object out of the DLL. Uses current + * DLL structure for iteration, starting at the DLL object that instantiates it. + * + */ + private class DLLIterator implements Iterator + { + DLL currentNode = DLL.this; + DLL firstObject = DLL.this; + boolean stop = false; + + @Override + public boolean hasNext() + { + return !stop && (currentNode != null && currentNode.object != null); + } + + @Override + public T next() + { + T currentObject = currentNode.object; + currentNode = currentNode.next(); + if (currentNode == firstObject) + stop = true; + + return currentObject; + } + + @Override + public void remove() + { + // optional method that is not needed in our case. + } + + } +} diff --git a/simplCore/src/ecologylab/collections/FilteredIterator.java b/simplCore/src/ecologylab/collections/FilteredIterator.java new file mode 100644 index 00000000..24b94248 --- /dev/null +++ b/simplCore/src/ecologylab/collections/FilteredIterator.java @@ -0,0 +1,69 @@ +package ecologylab.collections; + +import java.util.Iterator; + +/** + * A filtered iterator. + * + * @author quyin + * + * @param + */ +public abstract class FilteredIterator implements Iterator +{ + + Iterator iter; + + E nextItem; + + public FilteredIterator(Iterator origIter) + { + super(); + this.iter = origIter; + findNextItem(); + } + + /** + * + * @param element + * @return True if element should be kept in the filtered iterator. False otherwise. + */ + abstract protected boolean keepElement(E element); + + @Override + public boolean hasNext() + { + return nextItem != null; + } + + @Override + public E next() + { + E result = nextItem; + + findNextItem(); + + return result; + } + + private void findNextItem() + { + nextItem = null; + while (iter.hasNext()) + { + E element = iter.next(); + if (keepElement(element)) + { + nextItem = element; + return; + } + } + } + + @Override + public void remove() + { + throw new UnsupportedOperationException("FilteredIterator.remove() is not supported."); + } + +} diff --git a/simplCore/src/ecologylab/collections/FloatSetElement.java b/simplCore/src/ecologylab/collections/FloatSetElement.java index b3667350..f7290ffa 100644 --- a/simplCore/src/ecologylab/collections/FloatSetElement.java +++ b/simplCore/src/ecologylab/collections/FloatSetElement.java @@ -1,183 +1,183 @@ -/* - * Copyright 1996-2002 by Andruid Kerne. All rights reserved. - * CONFIDENTIAL. Use is subject to license terms. - */ -package ecologylab.collections; - -import ecologylab.generic.Debug; - -/** - * A FloatWeightSet element. - * - * Basic implementation of SetElement for cases when you can inherit from here - **/ -public class FloatSetElement -extends Debug -// implements SetElement -{ - - - public static final int NOT_A_MEMBER = -1; - - private int index = NOT_A_MEMBER; - - /** - * Cached version of weight. Made accessible for efficiency's sake. - * Use carefully, at your own risk, and only w inside, deep understanding. - */ - public float weight; - - BasicFloatSet set; - - public FloatSetElement() - { - } - public FloatSetElement(float initial) - { - weight = initial; - } - public float getWeight() - { - return weight; - } - /** - * This can be overridden to exclude elements from selection while keeping them in the set. - * - * @return The default implementation always returns false, including all elements for selection. - */ - public boolean filteredOut() - { - return false; - } - public int getIndex() - { - return index; - } - public void setIndex(int newIndex) - { - index = newIndex; - } - public void setSet(BasicFloatSet setArg) - { - set = setArg; - } - - public boolean isInSet() - { - return (set != null) && (index != NOT_A_MEMBER); - } - - /** - * Delete in the most expedient manner possible. - * This is final because you should override deleteHook() to provide - * custom behavior. - */ - public final void delete() - { - delete(BasicFloatSet.NO_RECOMPUTE); - } - /** - * Delete the element from the set. - * This means changing the set's structure, and also changing slots in - * this to reflect its lack of membership. - * - * @param recompute -1 for absolutely no recomputation of the set's internal structures. - * 0 for recompute upwards from el - * 1 for recompute all - * - * @return true if the element was a member of a set, and thus, if the delete does something; - * false if the element was not a member of a set, and thus, if the delete does *nothing*. - */ - public final synchronized boolean delete(int recompute) - { - boolean inSet = isInSet(); - if (inSet)//prevent double dip deletes - { - set.delete(this, recompute); - clear(); - } - return inSet; - } - - /** - * Callback that happens at the end of a delete, and when an element gets pruned. - * This implementation is empty. Override to provide custom behaviors. - */ - public void deleteHook() - { - - } - - /** - * A callback method for when an element is inserted into a floatWeightSet. - * - * This implementation is empty. Override to provide custom behaviors. - */ - public void insertHook() - { - - } - - /** - * Only for use by FloatWeightSet.clear(), and delete. - * This is used to reset state of this, in cases when the state - * of the FloatWeightSet we were part of is being reset some other way, - * or if it is being discarded. - * - */ - public void clear() - { - deleteHook(); - index = NOT_A_MEMBER; - set = null; - } - - /** - * A synchronized version of clear(), for use in FloatWeightSet.prune(). - * - */ - synchronized void clearSynch() - { - clear(); - } - /** - * Change the weight of the element, without propogating the new - * weight into the data structure. The result of the change will be - * propogated later by some other operation (such as delete) which - * performs a recompute - */ - public void delaySetWeight(float newWeight) - { - weight = newWeight; - } - /** - * Set the weight slot. - * - * Doesn't effect the set if no longer a member. - */ - public void setWeight(float newWeight) - { - weight = newWeight; - } - @Override -public String toString() - { - return super.toString() + " " + getIndex() + ": " + weight; - } - /** - * Free resources associated w this element. - */ - public boolean recycle() - { - return true; - } - /** - * The set object that this element is part of, or null if its not a member of any set. - * - * @return - */ - protected BasicFloatSet set() - { - return set; - } -} +/* + * Copyright 1996-2002 by Andruid Kerne. All rights reserved. + * CONFIDENTIAL. Use is subject to license terms. + */ +package ecologylab.collections; + +import ecologylab.generic.Debug; + +/** + * A FloatWeightSet element. + * + * Basic implementation of SetElement for cases when you can inherit from here + **/ +public class FloatSetElement +extends Debug +// implements SetElement +{ + + + public static final int NOT_A_MEMBER = -1; + + private int index = NOT_A_MEMBER; + + /** + * Cached version of weight. Made accessible for efficiency's sake. + * Use carefully, at your own risk, and only w inside, deep understanding. + */ + public float weight; + + BasicFloatSet set; + + public FloatSetElement() + { + } + public FloatSetElement(float initial) + { + weight = initial; + } + public float getWeight() + { + return weight; + } + /** + * This can be overridden to exclude elements from selection while keeping them in the set. + * + * @return The default implementation always returns false, including all elements for selection. + */ + public boolean filteredOut() + { + return false; + } + public int getIndex() + { + return index; + } + public void setIndex(int newIndex) + { + index = newIndex; + } + public void setSet(BasicFloatSet setArg) + { + set = setArg; + } + + public boolean isInSet() + { + return (set != null) && (index != NOT_A_MEMBER); + } + + /** + * Delete in the most expedient manner possible. + * This is final because you should override deleteHook() to provide + * custom behavior. + */ + public final void delete() + { + delete(BasicFloatSet.NO_RECOMPUTE); + } + /** + * Delete the element from the set. + * This means changing the set's structure, and also changing slots in + * this to reflect its lack of membership. + * + * @param recompute -1 for absolutely no recomputation of the set's internal structures. + * 0 for recompute upwards from el + * 1 for recompute all + * + * @return true if the element was a member of a set, and thus, if the delete does something; + * false if the element was not a member of a set, and thus, if the delete does *nothing*. + */ + public final synchronized boolean delete(int recompute) + { + boolean inSet = isInSet(); + if (inSet)//prevent double dip deletes + { + set.delete(this, recompute); + clear(); + } + return inSet; + } + + /** + * Callback that happens at the end of a delete, and when an element gets pruned. + * This implementation is empty. Override to provide custom behaviors. + */ + public void deleteHook() + { + + } + + /** + * A callback method for when an element is inserted into a floatWeightSet. + * + * This implementation is empty. Override to provide custom behaviors. + */ + public void insertHook() + { + + } + + /** + * Only for use by FloatWeightSet.clear(), and delete. + * This is used to reset state of this, in cases when the state + * of the FloatWeightSet we were part of is being reset some other way, + * or if it is being discarded. + * + */ + public void clear() + { + deleteHook(); + index = NOT_A_MEMBER; + set = null; + } + + /** + * A synchronized version of clear(), for use in FloatWeightSet.prune(). + * + */ + synchronized void clearSynch() + { + clear(); + } + /** + * Change the weight of the element, without propogating the new + * weight into the data structure. The result of the change will be + * propogated later by some other operation (such as delete) which + * performs a recompute + */ + public void delaySetWeight(float newWeight) + { + weight = newWeight; + } + /** + * Set the weight slot. + * + * Doesn't effect the set if no longer a member. + */ + public void setWeight(float newWeight) + { + weight = newWeight; + } + @Override +public String toString() + { + return super.toString() + " " + getIndex() + ": " + weight; + } + /** + * Free resources associated w this element. + */ + public boolean recycle() + { + return true; + } + /** + * The set object that this element is part of, or null if its not a member of any set. + * + * @return + */ + protected BasicFloatSet set() + { + return set; + } +} diff --git a/simplCore/src/ecologylab/collections/FloatWeightSet.java b/simplCore/src/ecologylab/collections/FloatWeightSet.java index e78fc580..0de5275f 100644 --- a/simplCore/src/ecologylab/collections/FloatWeightSet.java +++ b/simplCore/src/ecologylab/collections/FloatWeightSet.java @@ -1,947 +1,947 @@ -/* - * Copyright 1996-2002 by Andruid Kerne. All rights reserved. - * CONFIDENTIAL. Use is subject to license terms. - */ -package ecologylab.collections; - -import java.util.ArrayList; - -import ecologylab.generic.Debug; -import ecologylab.generic.Generic; -import ecologylab.generic.MathTools; -import ecologylab.generic.ThreadMaster; - -/** - * Provides the facility of efficient weighted random selection from a set - * elements, each of whicn includes a characterizing floating point weight. - *

- * - * Works in cooperation w FloatSetElements; requiring that - * user object to keep an integer index slot, which only we should be - * accessing. This impure oo style is an adaption to Java's lack of - * multiple inheritance. - *

- * - * Gotta be careful to be thread safe. - * Seems no operations can safely occur concurrently. - * There are a bunch of synchronized methods to affect this. - **/ -public class FloatWeightSet -extends Debug implements BasicFloatSet -{ - - public final class DefaultWeightStrategy extends WeightingStrategy - { - @Override - public double getWeight(E e) { - return e.getWeight(); - } - @Override - public boolean hasChanged() { - return true; - } - }; - - private WeightingStrategy getWeightStrategy = new DefaultWeightStrategy(); - - public void setWeightingStrategy(WeightingStrategy getWeightStrategy) - { - this.getWeightStrategy = getWeightStrategy; - } - - /** - * An array representation of the members of the set. - * Kind of like a java.util.ArrayList, but faster. - */ - private FloatSetElement elements[]; - - /** - * Used to maintain a sequential set of areas by weight, in order - * to implement fast weighted randomSelect(). - */ - protected float incrementalSums[]; - - protected float setSum = 0; - - - /** - * Used as a boundary condition for fast implementations of sort. - */ - protected final FloatSetElement SENTINEL = new FloatSetElement(); - - /** - * This might pause us before we do an expensive operation. - */ - ThreadMaster threadMaster; - - static final int PRUNE_PRIORITY = 1; - - /** - * Sets should get pruned when their size is this much larger than - * what the caller originally specified. - */ - static final int PRUNE_LEVEL = 0; - - /** - * This many extra slots will be allocated in the set, to enable insertions() - * prior to a prune(), without reallocation. - */ - protected final int extraAllocation; - - /** - * Allocate this many extra slots, to avoid needing to alloc due to synch - * issues between insert & prune. - */ - public static final int EXTRA_ALLOCATION = 256; - - /** - * size of last used element in array - */ - protected int size; - /** - * size of the array. (Some upper slots are likely unused.) - */ - int numSlots; - - /** - * Maximum size to let this grow to, before needPrune() will return true. - * That is, when the set grows larger than this, it should be prune()ed. - */ - protected int pruneSize; - - /** - * When there is more than one maximum found by maxSelect(), this ArrayList - * holds the tied elements. That this is not either a temporary, or - * passed back as the result of the sort operation, is hackish. - */ - protected ArrayList maxArrayList; - - /** - * For managing sort operations - */ - static final int TOO_SMALL_TO_QUICKSORT = 10; - - /** - * Create a set, with data structures to support the stated initial size. - * This set will not support weightedRandomSelect(). - */ - public FloatWeightSet(int initialSize) - { - this(initialSize, null, false); - } - public FloatWeightSet(int initialSize, boolean supportWeightedRandomSelect) - { - this(initialSize, null, supportWeightedRandomSelect); - } - /** - * Create a set, with data structures to support the stated initial - * size, and a threadMaster that may pause use before expensive operations. - * This set will not support weightedRandomSelect(). - */ - public FloatWeightSet(int initialSize, ThreadMaster threadMaster) - { - this(initialSize, threadMaster, false); - } - public FloatWeightSet(int initialSize, ThreadMaster threadMaster, - boolean supportWeightedRandomSelect) - { - //this(initialSize, EXTRA_ALLOCATION, threadMaster, - this(initialSize, initialSize/2, threadMaster, - supportWeightedRandomSelect); - } - - /** - * Create a set, with data structures to support the stated initial - * size, and a threadMaster that may pause use before expensive operations. - * This set may support weightedRandomSelect(). - */ - public FloatWeightSet(int initialSize, int extraAllocation, - ThreadMaster threadMaster, - boolean supportWeightedRandomSelect) - { - this.threadMaster = threadMaster; - this.extraAllocation = extraAllocation; - - size = 0; - pruneSize = initialSize + extraAllocation/2; - - alloc(initialSize + PRUNE_LEVEL + extraAllocation, supportWeightedRandomSelect); - SENTINEL.weight = - Float.MAX_VALUE; - basicInsert(SENTINEL); - //debug("constructed w numSlots=" + numSlots + " maxSize=" + pruneSize + " extraAllocation="+extraAllocation); - } - private final void alloc(int allocSize, boolean supportWeightedRandomSelect) - { - elements = new FloatSetElement[allocSize]; - numSlots = allocSize; - - if (supportWeightedRandomSelect) - { - incrementalSums = new float[allocSize]; - } - } - /** - * Delete all the elements in the set, as fast as possible. - * @param doRecycleElements TODO - * - */ - public synchronized void clear(boolean doRecycleElements) - { - for (int i=0; i " + allocSize + " slots"); - FloatSetElement newElements[] = new FloatSetElement[allocSize]; - numSlots = allocSize; - // finish housekeeping - System.arraycopy(elements,0, newElements,0, size); - elements = newElements; - if (incrementalSums != null) - { - float newSums[] = new float[allocSize];; - System.arraycopy(incrementalSums,0, newSums, 0, size); - incrementalSums = newSums; - } - } - // start insert - basicInsert(el); - el.insertHook(); - } - /** - * Internals of the insert. - * - * @param el - */ - private void basicInsert(FloatSetElement el) - { - el.setSet(this); - elements[size] = el; - - if( size!= 0 ) - setSum += getWeightStrategy.getWeight(el); - - el.setIndex(size++); - - - } - /** - * Delete an element from the set. - * Perhaps recompute incremental sums for randomSelect() integrity. - * Includes ensuring we cant pick el again. - *

- * This method MUST ONLY be called by FloatSetElement.delete()! - * - * @param el The FloatSetElement element to delete. - * @param recompute -1 for absolutely no recompute. - * 0 for recompute upwards from el. - * 1 for recompute all. - **/ - @Override -public synchronized void delete(E el, int recompute) - { - int index = el.getIndex(); - if ((size == 0) || (index < 0)) - return; - // ???!!! return NaN; - // float finalWeight = el.getWeight(); - int lastIndex = --size; - if (index != lastIndex) // if not the last element - { - // swap the last element from down there - FloatSetElement lastElement; - // ??? this is a workaround for some horrendous bug that is - // corrupting this data structure !!! - while ((lastElement = elements[lastIndex]) == null) - { - size--; - lastIndex--; - } - synchronized (lastElement) - { - elements[index] = lastElement; - elements[lastIndex] = null; // remove reference to allow gc - lastElement.setIndex(index); - - setSum -= getWeightStrategy.getWeight(el); - } - if (recompute != NO_RECOMPUTE) - { - int recomputeIndex = (recompute == RECOMPUTE_ALL) ? 0 : index; - syncRecompute(recomputeIndex); - } - } - getWeightStrategy.remove(el); - } - public boolean pruneIfNeeded() - { - int pruneSize = this.pruneSize; - boolean result = isOversize(pruneSize); - if (result) - prune(pruneSize); - return result; - } - /** - * Return true if the size of this is greater than the threshold passed in. - * - * @param sizeThreshold - * @return - */ - protected boolean isOversize(int sizeThreshold) - { - return (size >= sizeThreshold); - } - - /** - * Prune to the set's specified maxSize, if necessary, then do a maxSelect(). - * The reason for doing these operations together is because both require sorting. - * - * @return element in the set with the highest weight, or in case of a tie, - * a random pick of those. - */ - public synchronized E pruneAndMaxSelect() - { - return maxSelect(pruneSize); - } - /** - * Prune to the specified desired size, if necessary, then do a maxSelect(). - * - * @param desiredSize - * @return element in the set with the highest weight, or in case of a tie, - * a random pick of those. - */ - public synchronized E maxSelect(int desiredSize) - { - if (isOversize(desiredSize)) - prune(desiredSize); - Thread.yield(); - FloatSetElement result = maxSelect(); - if (result == SENTINEL) - { // defensive programming - debug("maxSelect() ERROR chose sentinel??????!!! size="+ size +" maxArrayListSize="+maxArrayList.size()); - Thread.dumpStack(); - if (size > 1) - result = elements[--size]; - else - result = null; - } - if (result != null) - result.delete(NO_RECOMPUTE); - return (E) result; - } - /** - * Clear the ArrayList of tied elements from the last maxSelect(). - * This method can be overridden to provide post-process before the actual clear. - *

- * The clear() should be done as part of maxSelect() to avoid memory leaks. - */ - protected void maxArrayListClear() - { - if (maxArrayList != null) - maxArrayList.clear(); - } - /** - * @return the maximum in the set. If there are ties, pick - * randomly among them - */ - public synchronized E maxSelect() - { - int size = this.size; - switch (size) - { - case 0: // should never happen cause of sentinel - case 1: // degenerate case (look out for the sentinel!) - return null; - case 2: - return (E) elements[1]; - default: // now, size >= 3! - break; - } - - if (maxArrayList == null) - { - int arrayListSize = size / 8; - if (arrayListSize > 1024) - arrayListSize = 1024; - maxArrayList = new ArrayList(arrayListSize); - } - else - maxArrayList.clear(); - - //set result in case there's only 1 element in the set. - FloatSetElement result= SENTINEL; - float maxWeight = (float) getWeightStrategy.getWeight(result); - - setSum = 0; - - for (int i=1; i maxWeight) - { - maxArrayList.clear(); - result = thatElement; - maxWeight = thatWeight; - maxArrayList.add(thatElement); - } - else if (thatWeight == maxWeight) - { - maxArrayList.add(thatElement); - } - } - else - { - // debug("MAX SELECT FILTERED " + thatElement); - } - } - - if (result == SENTINEL) - return null; - - int numMax = maxArrayList.size(); - - //if there are more than one in our set, there is a tie, so choose which to get! - if (numMax > 1) - result = maxArrayList.get(MathTools.random(numMax)); - //maxArrayListClear(); - - return (E) result; - } - - /** - * If there was a tie in the last maxSelect() calculation, the others will be here. - * - * @return - */ - public ArrayList tiedForMax() - { - return maxArrayList; - } - /** - * Delete lowest-weighted elements, in case this collection has grown too big. - * (After all, we can't have the INFINITELY LARGE collections we'd really like.) - * @param numToKeep -- size for the set after pruning is done. - */ - public synchronized void prune(int numToKeep) - { - int size = this.size; - if (size <= numToKeep) - return; - long startTime = System.currentTimeMillis(); - debug("prune("+ size +" > "+ numToKeep+")"); - if (threadMaster != null) - { - debug("pause threads and sleep briefly"); - threadMaster.pauseThreads(); - Generic.sleep(2000); - } - Thread currentThread = Thread.currentThread(); - int priority = currentThread.getPriority(); - if (PRUNE_PRIORITY < priority) - currentThread.setPriority(PRUNE_PRIORITY); - //------------------ update weights ------------------// - for (int i=0; i= elements.length) - debug(".SHOCK i="+i + " size="+size+ " numSlots="+numSlots); - FloatSetElement thatElement = elements[i]; - if (thatElement != null) - { - elements[i] = null; // its deleted or moved; null either way - // thatElement.setSet(null); // make sure its treated as not here - // debug("recycling " + thatElement); - // a&n 9/12/07 - thatElement.setIndex(-1); // during gc() excursion - - // must be called *before* recycle(), because recycle() destroys needed data structures - thatElement.clearSynch(); - if (!thatElement.recycle()) // ??? create recursive havoc ??? FIX THIS! - { - weird("Prune but recycle() returned false: " + thatElement); - // a&n 9/12/07 - insert(thatElement); // put it back in the right place! - } - } - } - long duration = System.currentTimeMillis() - startTime; - if (PRUNE_PRIORITY < priority) - currentThread.setPriority(priority); - if (threadMaster != null) - { - debug("prune() unpause threads"); - threadMaster.unpauseThreads(); - //Generic.sleep(1000); - } - debug("prune() finished " + duration); - } - - /** - * Mean of elements in this set and another set. - * - * @param other The other FloatWeightSet, to include (weighted by number of elements) in the mean calculation. - * - * @return - */ - public synchronized float mean(FloatWeightSet other) - { - int numThis = other.size(); - int numOther = this.size(); - int numTotal = numThis + numOther; - if (numTotal == 0) - return 0; - return (numThis*other.mean() + numOther*this.mean()) / numTotal; - } - - - /** - * - * @return Mean of elements in the set. 0 if the set is empty. - */ - public synchronized float mean() - { - float result; - if (size == 0 || size==1) - result = 0; - else - { - if ( incrementalSums != null ) - result = incrementalSums[size - 1] / (size-1); - else if( setSum != 0 ) - { - result = setSum / (size-1); - } - else - { - float sum = 0; - int num = 0; - for (int i=1; i>> FloatWeightSet.recompute() size="+size); - // recompute sums above there - float sum = 0; - if (index > 0) - sum = incrementalSums[index - 1]; - int beyond = size; - int i=0; - try - { - for (i=index; i!=beyond; i++) - { - FloatSetElement element= elements[i]; - if (element == null) - { - String errorScene ="recompute() ERROR at i=" + - i + " w beyond=" + beyond + " in " + this; - System.out.println(errorScene + ".\nTrying to heal thyself."); - FloatSetElement lastElement = elements[--beyond]; - elements[i] = lastElement; - elements[beyond] = null; // remove reference in case of gc - i--; // process the new one delete will swap down - size--; - } - else - { - float weight = (float)getWeightStrategy.getWeight(element); - // ??? This kludge tries to avoid nasty errors. - // Still it's kind of a bad idea, cause it hides dynamic - // range problems that should be fixed elsewhere. - if ((weight != Float.NaN) && (weight > 0) && - (weight != Float.POSITIVE_INFINITY)) - sum += weight; - incrementalSums[i] = sum; - } - } - } catch (Exception e) - { - String errorScene ="\recompute() ERROR at i=" + - i + " w beyond=" + beyond + " in " + this; - debug(errorScene); - e.printStackTrace(); - } - return (size > 1) && (sum > 3.0E-45f) && (sum != Float.NaN) && - (sum != Float.POSITIVE_INFINITY); - } - - /** - * prune() if necessary, then syncRecompute(). - * Then do weighted randomSelect(). - * After the selection, delete the item from the set. - * - * @param desiredSize -- - * If size of the set >= 2 * desiredSize, gc() down - * to desiredSize. - * If 0, never gc. - * - * @return Selected - */ - - // Accessors for MediaSetState - //////////////////////////////////////////////////////// - public FloatSetElement[] elements() - { - return elements; - } - //TODO -- this looks like it will break sentinel! - public void setElements(FloatSetElement[] newElements) - { - elements = newElements; - } - public float[] incrementalSums() - { - return incrementalSums; - } - public void setIncrementalSums(float[] newIncrementalSums) - { - incrementalSums = newIncrementalSums; - } - - public int numSlots() - { - return numSlots; - } - public void setNumSlots(int newNumSlots) - { - numSlots = newNumSlots; - } - public void setSize(int newSize) - { - size = newSize; - } - public void initializeStructure(int size) - { - alloc(size, true); - } - - /** - * Set the maximum size this should grow to before pruning. - * - * @param maxSize The maxSize to set. - */ - public void setPruneSize(int maxSize) - { - this.pruneSize = maxSize; - } - /** - * Get the maximum size this should grow to before pruning. - */ - public int getPruneSize() - { - return pruneSize; - } - - @Override -public void decrement(E el) {} - - /** - * Method Overriden by {@link cf.model.VisualPool VisualPool} to return true - * @return - */ - public boolean isRunnable() - { - return false; - } -} +/* + * Copyright 1996-2002 by Andruid Kerne. All rights reserved. + * CONFIDENTIAL. Use is subject to license terms. + */ +package ecologylab.collections; + +import java.util.ArrayList; + +import ecologylab.generic.Debug; +import ecologylab.generic.Generic; +import ecologylab.generic.MathTools; +import ecologylab.generic.ThreadMaster; + +/** + * Provides the facility of efficient weighted random selection from a set + * elements, each of whicn includes a characterizing floating point weight. + *

+ * + * Works in cooperation w FloatSetElements; requiring that + * user object to keep an integer index slot, which only we should be + * accessing. This impure oo style is an adaption to Java's lack of + * multiple inheritance. + *

+ * + * Gotta be careful to be thread safe. + * Seems no operations can safely occur concurrently. + * There are a bunch of synchronized methods to affect this. + **/ +public class FloatWeightSet +extends Debug implements BasicFloatSet +{ + + public final class DefaultWeightStrategy extends WeightingStrategy + { + @Override + public double getWeight(E e) { + return e.getWeight(); + } + @Override + public boolean hasChanged() { + return true; + } + }; + + private WeightingStrategy getWeightStrategy = new DefaultWeightStrategy(); + + public void setWeightingStrategy(WeightingStrategy getWeightStrategy) + { + this.getWeightStrategy = getWeightStrategy; + } + + /** + * An array representation of the members of the set. + * Kind of like a java.util.ArrayList, but faster. + */ + private FloatSetElement elements[]; + + /** + * Used to maintain a sequential set of areas by weight, in order + * to implement fast weighted randomSelect(). + */ + protected float incrementalSums[]; + + protected float setSum = 0; + + + /** + * Used as a boundary condition for fast implementations of sort. + */ + protected final FloatSetElement SENTINEL = new FloatSetElement(); + + /** + * This might pause us before we do an expensive operation. + */ + ThreadMaster threadMaster; + + static final int PRUNE_PRIORITY = 1; + + /** + * Sets should get pruned when their size is this much larger than + * what the caller originally specified. + */ + static final int PRUNE_LEVEL = 0; + + /** + * This many extra slots will be allocated in the set, to enable insertions() + * prior to a prune(), without reallocation. + */ + protected final int extraAllocation; + + /** + * Allocate this many extra slots, to avoid needing to alloc due to synch + * issues between insert & prune. + */ + public static final int EXTRA_ALLOCATION = 256; + + /** + * size of last used element in array + */ + protected int size; + /** + * size of the array. (Some upper slots are likely unused.) + */ + int numSlots; + + /** + * Maximum size to let this grow to, before needPrune() will return true. + * That is, when the set grows larger than this, it should be prune()ed. + */ + protected int pruneSize; + + /** + * When there is more than one maximum found by maxSelect(), this ArrayList + * holds the tied elements. That this is not either a temporary, or + * passed back as the result of the sort operation, is hackish. + */ + protected ArrayList maxArrayList; + + /** + * For managing sort operations + */ + static final int TOO_SMALL_TO_QUICKSORT = 10; + + /** + * Create a set, with data structures to support the stated initial size. + * This set will not support weightedRandomSelect(). + */ + public FloatWeightSet(int initialSize) + { + this(initialSize, null, false); + } + public FloatWeightSet(int initialSize, boolean supportWeightedRandomSelect) + { + this(initialSize, null, supportWeightedRandomSelect); + } + /** + * Create a set, with data structures to support the stated initial + * size, and a threadMaster that may pause use before expensive operations. + * This set will not support weightedRandomSelect(). + */ + public FloatWeightSet(int initialSize, ThreadMaster threadMaster) + { + this(initialSize, threadMaster, false); + } + public FloatWeightSet(int initialSize, ThreadMaster threadMaster, + boolean supportWeightedRandomSelect) + { + //this(initialSize, EXTRA_ALLOCATION, threadMaster, + this(initialSize, initialSize/2, threadMaster, + supportWeightedRandomSelect); + } + + /** + * Create a set, with data structures to support the stated initial + * size, and a threadMaster that may pause use before expensive operations. + * This set may support weightedRandomSelect(). + */ + public FloatWeightSet(int initialSize, int extraAllocation, + ThreadMaster threadMaster, + boolean supportWeightedRandomSelect) + { + this.threadMaster = threadMaster; + this.extraAllocation = extraAllocation; + + size = 0; + pruneSize = initialSize + extraAllocation/2; + + alloc(initialSize + PRUNE_LEVEL + extraAllocation, supportWeightedRandomSelect); + SENTINEL.weight = - Float.MAX_VALUE; + basicInsert(SENTINEL); + //debug("constructed w numSlots=" + numSlots + " maxSize=" + pruneSize + " extraAllocation="+extraAllocation); + } + private final void alloc(int allocSize, boolean supportWeightedRandomSelect) + { + elements = new FloatSetElement[allocSize]; + numSlots = allocSize; + + if (supportWeightedRandomSelect) + { + incrementalSums = new float[allocSize]; + } + } + /** + * Delete all the elements in the set, as fast as possible. + * @param doRecycleElements TODO + * + */ + public synchronized void clear(boolean doRecycleElements) + { + for (int i=0; i " + allocSize + " slots"); + FloatSetElement newElements[] = new FloatSetElement[allocSize]; + numSlots = allocSize; + // finish housekeeping + System.arraycopy(elements,0, newElements,0, size); + elements = newElements; + if (incrementalSums != null) + { + float newSums[] = new float[allocSize];; + System.arraycopy(incrementalSums,0, newSums, 0, size); + incrementalSums = newSums; + } + } + // start insert + basicInsert(el); + el.insertHook(); + } + /** + * Internals of the insert. + * + * @param el + */ + private void basicInsert(FloatSetElement el) + { + el.setSet(this); + elements[size] = el; + + if( size!= 0 ) + setSum += getWeightStrategy.getWeight(el); + + el.setIndex(size++); + + + } + /** + * Delete an element from the set. + * Perhaps recompute incremental sums for randomSelect() integrity. + * Includes ensuring we cant pick el again. + *

+ * This method MUST ONLY be called by FloatSetElement.delete()! + * + * @param el The FloatSetElement element to delete. + * @param recompute -1 for absolutely no recompute. + * 0 for recompute upwards from el. + * 1 for recompute all. + **/ + @Override +public synchronized void delete(E el, int recompute) + { + int index = el.getIndex(); + if ((size == 0) || (index < 0)) + return; + // ???!!! return NaN; + // float finalWeight = el.getWeight(); + int lastIndex = --size; + if (index != lastIndex) // if not the last element + { + // swap the last element from down there + FloatSetElement lastElement; + // ??? this is a workaround for some horrendous bug that is + // corrupting this data structure !!! + while ((lastElement = elements[lastIndex]) == null) + { + size--; + lastIndex--; + } + synchronized (lastElement) + { + elements[index] = lastElement; + elements[lastIndex] = null; // remove reference to allow gc + lastElement.setIndex(index); + + setSum -= getWeightStrategy.getWeight(el); + } + if (recompute != NO_RECOMPUTE) + { + int recomputeIndex = (recompute == RECOMPUTE_ALL) ? 0 : index; + syncRecompute(recomputeIndex); + } + } + getWeightStrategy.remove(el); + } + public boolean pruneIfNeeded() + { + int pruneSize = this.pruneSize; + boolean result = isOversize(pruneSize); + if (result) + prune(pruneSize); + return result; + } + /** + * Return true if the size of this is greater than the threshold passed in. + * + * @param sizeThreshold + * @return + */ + protected boolean isOversize(int sizeThreshold) + { + return (size >= sizeThreshold); + } + + /** + * Prune to the set's specified maxSize, if necessary, then do a maxSelect(). + * The reason for doing these operations together is because both require sorting. + * + * @return element in the set with the highest weight, or in case of a tie, + * a random pick of those. + */ + public synchronized E pruneAndMaxSelect() + { + return maxSelect(pruneSize); + } + /** + * Prune to the specified desired size, if necessary, then do a maxSelect(). + * + * @param desiredSize + * @return element in the set with the highest weight, or in case of a tie, + * a random pick of those. + */ + public synchronized E maxSelect(int desiredSize) + { + if (isOversize(desiredSize)) + prune(desiredSize); + Thread.yield(); + FloatSetElement result = maxSelect(); + if (result == SENTINEL) + { // defensive programming + debug("maxSelect() ERROR chose sentinel??????!!! size="+ size +" maxArrayListSize="+maxArrayList.size()); + Thread.dumpStack(); + if (size > 1) + result = elements[--size]; + else + result = null; + } + if (result != null) + result.delete(NO_RECOMPUTE); + return (E) result; + } + /** + * Clear the ArrayList of tied elements from the last maxSelect(). + * This method can be overridden to provide post-process before the actual clear. + *

+ * The clear() should be done as part of maxSelect() to avoid memory leaks. + */ + protected void maxArrayListClear() + { + if (maxArrayList != null) + maxArrayList.clear(); + } + /** + * @return the maximum in the set. If there are ties, pick + * randomly among them + */ + public synchronized E maxSelect() + { + int size = this.size; + switch (size) + { + case 0: // should never happen cause of sentinel + case 1: // degenerate case (look out for the sentinel!) + return null; + case 2: + return (E) elements[1]; + default: // now, size >= 3! + break; + } + + if (maxArrayList == null) + { + int arrayListSize = size / 8; + if (arrayListSize > 1024) + arrayListSize = 1024; + maxArrayList = new ArrayList(arrayListSize); + } + else + maxArrayList.clear(); + + //set result in case there's only 1 element in the set. + FloatSetElement result= SENTINEL; + float maxWeight = (float) getWeightStrategy.getWeight(result); + + setSum = 0; + + for (int i=1; i maxWeight) + { + maxArrayList.clear(); + result = thatElement; + maxWeight = thatWeight; + maxArrayList.add(thatElement); + } + else if (thatWeight == maxWeight) + { + maxArrayList.add(thatElement); + } + } + else + { + // debug("MAX SELECT FILTERED " + thatElement); + } + } + + if (result == SENTINEL) + return null; + + int numMax = maxArrayList.size(); + + //if there are more than one in our set, there is a tie, so choose which to get! + if (numMax > 1) + result = maxArrayList.get(MathTools.random(numMax)); + //maxArrayListClear(); + + return (E) result; + } + + /** + * If there was a tie in the last maxSelect() calculation, the others will be here. + * + * @return + */ + public ArrayList tiedForMax() + { + return maxArrayList; + } + /** + * Delete lowest-weighted elements, in case this collection has grown too big. + * (After all, we can't have the INFINITELY LARGE collections we'd really like.) + * @param numToKeep -- size for the set after pruning is done. + */ + public synchronized void prune(int numToKeep) + { + int size = this.size; + if (size <= numToKeep) + return; + long startTime = System.currentTimeMillis(); + debug("prune("+ size +" > "+ numToKeep+")"); + if (threadMaster != null) + { + debug("pause threads and sleep briefly"); + threadMaster.pauseThreads(); + Generic.sleep(2000); + } + Thread currentThread = Thread.currentThread(); + int priority = currentThread.getPriority(); + if (PRUNE_PRIORITY < priority) + currentThread.setPriority(PRUNE_PRIORITY); + //------------------ update weights ------------------// + for (int i=0; i= elements.length) + debug(".SHOCK i="+i + " size="+size+ " numSlots="+numSlots); + FloatSetElement thatElement = elements[i]; + if (thatElement != null) + { + elements[i] = null; // its deleted or moved; null either way + // thatElement.setSet(null); // make sure its treated as not here + // debug("recycling " + thatElement); + // a&n 9/12/07 - thatElement.setIndex(-1); // during gc() excursion + + // must be called *before* recycle(), because recycle() destroys needed data structures + thatElement.clearSynch(); + if (!thatElement.recycle()) // ??? create recursive havoc ??? FIX THIS! + { + weird("Prune but recycle() returned false: " + thatElement); + // a&n 9/12/07 - insert(thatElement); // put it back in the right place! + } + } + } + long duration = System.currentTimeMillis() - startTime; + if (PRUNE_PRIORITY < priority) + currentThread.setPriority(priority); + if (threadMaster != null) + { + debug("prune() unpause threads"); + threadMaster.unpauseThreads(); + //Generic.sleep(1000); + } + debug("prune() finished " + duration); + } + + /** + * Mean of elements in this set and another set. + * + * @param other The other FloatWeightSet, to include (weighted by number of elements) in the mean calculation. + * + * @return + */ + public synchronized float mean(FloatWeightSet other) + { + int numThis = other.size(); + int numOther = this.size(); + int numTotal = numThis + numOther; + if (numTotal == 0) + return 0; + return (numThis*other.mean() + numOther*this.mean()) / numTotal; + } + + + /** + * + * @return Mean of elements in the set. 0 if the set is empty. + */ + public synchronized float mean() + { + float result; + if (size == 0 || size==1) + result = 0; + else + { + if ( incrementalSums != null ) + result = incrementalSums[size - 1] / (size-1); + else if( setSum != 0 ) + { + result = setSum / (size-1); + } + else + { + float sum = 0; + int num = 0; + for (int i=1; i>> FloatWeightSet.recompute() size="+size); + // recompute sums above there + float sum = 0; + if (index > 0) + sum = incrementalSums[index - 1]; + int beyond = size; + int i=0; + try + { + for (i=index; i!=beyond; i++) + { + FloatSetElement element= elements[i]; + if (element == null) + { + String errorScene ="recompute() ERROR at i=" + + i + " w beyond=" + beyond + " in " + this; + System.out.println(errorScene + ".\nTrying to heal thyself."); + FloatSetElement lastElement = elements[--beyond]; + elements[i] = lastElement; + elements[beyond] = null; // remove reference in case of gc + i--; // process the new one delete will swap down + size--; + } + else + { + float weight = (float)getWeightStrategy.getWeight(element); + // ??? This kludge tries to avoid nasty errors. + // Still it's kind of a bad idea, cause it hides dynamic + // range problems that should be fixed elsewhere. + if ((weight != Float.NaN) && (weight > 0) && + (weight != Float.POSITIVE_INFINITY)) + sum += weight; + incrementalSums[i] = sum; + } + } + } catch (Exception e) + { + String errorScene ="\recompute() ERROR at i=" + + i + " w beyond=" + beyond + " in " + this; + debug(errorScene); + e.printStackTrace(); + } + return (size > 1) && (sum > 3.0E-45f) && (sum != Float.NaN) && + (sum != Float.POSITIVE_INFINITY); + } + + /** + * prune() if necessary, then syncRecompute(). + * Then do weighted randomSelect(). + * After the selection, delete the item from the set. + * + * @param desiredSize -- + * If size of the set >= 2 * desiredSize, gc() down + * to desiredSize. + * If 0, never gc. + * + * @return Selected + */ + + // Accessors for MediaSetState + //////////////////////////////////////////////////////// + public FloatSetElement[] elements() + { + return elements; + } + //TODO -- this looks like it will break sentinel! + public void setElements(FloatSetElement[] newElements) + { + elements = newElements; + } + public float[] incrementalSums() + { + return incrementalSums; + } + public void setIncrementalSums(float[] newIncrementalSums) + { + incrementalSums = newIncrementalSums; + } + + public int numSlots() + { + return numSlots; + } + public void setNumSlots(int newNumSlots) + { + numSlots = newNumSlots; + } + public void setSize(int newSize) + { + size = newSize; + } + public void initializeStructure(int size) + { + alloc(size, true); + } + + /** + * Set the maximum size this should grow to before pruning. + * + * @param maxSize The maxSize to set. + */ + public void setPruneSize(int maxSize) + { + this.pruneSize = maxSize; + } + /** + * Get the maximum size this should grow to before pruning. + */ + public int getPruneSize() + { + return pruneSize; + } + + @Override +public void decrement(E el) {} + + /** + * Method Overriden by {@link cf.model.VisualPool VisualPool} to return true + * @return + */ + public boolean isRunnable() + { + return false; + } +} diff --git a/simplCore/src/ecologylab/collections/HashMapWriteSynch3Args.java b/simplCore/src/ecologylab/collections/HashMapWriteSynch3Args.java index bea1ff10..1fb27a58 100644 --- a/simplCore/src/ecologylab/collections/HashMapWriteSynch3Args.java +++ b/simplCore/src/ecologylab/collections/HashMapWriteSynch3Args.java @@ -1,112 +1,112 @@ -/** - * - */ -package ecologylab.collections; - -import java.util.Map; - -import ecologylab.generic.HashMapWriteSynchBase; - - -/** - * Hashed data structure with synchronized writes/deletes and unsynchronized reads. - * Value factory takes 3 args. First one is the key. - * - * - * @author andruid @param Type of the Key. - * @author andruid @param Type the value factory returns. Usually the same as type of Key, it can also extend it. - * Also the type of an argument to the value factory. - * @author andruid @param Type of the value. - * @author andruid @param Type of an argument to the value factory. - * @author andruid @param Type of an argument to the value factory. - */ -public class HashMapWriteSynch3Args extends HashMapWriteSynchBase -{ - ValueFactory3 valueFactory; - -/** - * - * @param size - * @param load - */ - public HashMapWriteSynch3Args(int size, float load) - { - super(size, load); - } - - public HashMapWriteSynch3Args(int size, float load, ValueFactory3 valueFactory) - { - this(size, load); - this.valueFactory = valueFactory; - } - /** - * @param arg0 - */ - public HashMapWriteSynch3Args(int arg0) - { - super(arg0); - // TODO Auto-generated constructor stub - } - - /** - * - */ - public HashMapWriteSynch3Args() - { - // TODO Auto-generated constructor stub - } - - /** - * @param arg0 - */ - public HashMapWriteSynch3Args(Map arg0) - { - super(arg0); - // TODO Auto-generated constructor stub - } - - /** - * If there is already an entry, return it. - * Otherwise, create an entry with the valueFactory slot of this. - * - * @param key - * @param arg1 - * @param arg2 - * - * @return The key matching value, found or constructed. - */ - public V getOrCreateAndPutIfNew(K2 key, A1 arg1, A2 arg2) - { - return getOrCreateAndPutIfNew(key, arg1, arg2, valueFactory); - } - - /** - * If there is already an entry, return it. - * Otherwise, create an entry with the factory. - * - * @param key - * @param arg1 - * @param arg2 - * @param factory - * - * @return The key matching value, found or constructed. - */ - public V getOrCreateAndPutIfNew(K2 key, A1 arg1, A2 arg2, ValueFactory3 factory) - { - V result = get(key); - if (result == null) - { - synchronized (this) - { - result = get(key); - if (result == null) - { - result = factory.createValue(key, arg1, arg2); - super.put(key, result); - } - } - } - return result; - } - -} +/** + * + */ +package ecologylab.collections; + +import java.util.Map; + +import ecologylab.generic.HashMapWriteSynchBase; + + +/** + * Hashed data structure with synchronized writes/deletes and unsynchronized reads. + * Value factory takes 3 args. First one is the key. + * + * + * @author andruid @param Type of the Key. + * @author andruid @param Type the value factory returns. Usually the same as type of Key, it can also extend it. + * Also the type of an argument to the value factory. + * @author andruid @param Type of the value. + * @author andruid @param Type of an argument to the value factory. + * @author andruid @param Type of an argument to the value factory. + */ +public class HashMapWriteSynch3Args extends HashMapWriteSynchBase +{ + ValueFactory3 valueFactory; + +/** + * + * @param size + * @param load + */ + public HashMapWriteSynch3Args(int size, float load) + { + super(size, load); + } + + public HashMapWriteSynch3Args(int size, float load, ValueFactory3 valueFactory) + { + this(size, load); + this.valueFactory = valueFactory; + } + /** + * @param arg0 + */ + public HashMapWriteSynch3Args(int arg0) + { + super(arg0); + // TODO Auto-generated constructor stub + } + + /** + * + */ + public HashMapWriteSynch3Args() + { + // TODO Auto-generated constructor stub + } + + /** + * @param arg0 + */ + public HashMapWriteSynch3Args(Map arg0) + { + super(arg0); + // TODO Auto-generated constructor stub + } + + /** + * If there is already an entry, return it. + * Otherwise, create an entry with the valueFactory slot of this. + * + * @param key + * @param arg1 + * @param arg2 + * + * @return The key matching value, found or constructed. + */ + public V getOrCreateAndPutIfNew(K2 key, A1 arg1, A2 arg2) + { + return getOrCreateAndPutIfNew(key, arg1, arg2, valueFactory); + } + + /** + * If there is already an entry, return it. + * Otherwise, create an entry with the factory. + * + * @param key + * @param arg1 + * @param arg2 + * @param factory + * + * @return The key matching value, found or constructed. + */ + public V getOrCreateAndPutIfNew(K2 key, A1 arg1, A2 arg2, ValueFactory3 factory) + { + V result = get(key); + if (result == null) + { + synchronized (this) + { + result = get(key); + if (result == null) + { + result = factory.createValue(key, arg1, arg2); + super.put(key, result); + } + } + } + return result; + } + +} diff --git a/simplCore/src/ecologylab/collections/LinearAccess.java b/simplCore/src/ecologylab/collections/LinearAccess.java index 422672fb..167f1b75 100644 --- a/simplCore/src/ecologylab/collections/LinearAccess.java +++ b/simplCore/src/ecologylab/collections/LinearAccess.java @@ -1,23 +1,23 @@ -/** - * - */ -package ecologylab.collections; - -/** - * @author eunyee - * - */ -public interface LinearAccess -{ - /** - * Return the ith element in the collection. - * @param i - * @return - */ - public E get(int i); - - public int size(); - - public boolean isEmpty(); - -} +/** + * + */ +package ecologylab.collections; + +/** + * @author eunyee + * + */ +public interface LinearAccess +{ + /** + * Return the ith element in the collection. + * @param i + * @return + */ + public E get(int i); + + public int size(); + + public boolean isEmpty(); + +} diff --git a/simplCore/src/ecologylab/collections/MergeD.java b/simplCore/src/ecologylab/collections/MergeD.java index dbd679e0..b6e021f1 100644 --- a/simplCore/src/ecologylab/collections/MergeD.java +++ b/simplCore/src/ecologylab/collections/MergeD.java @@ -1,22 +1,22 @@ -/* - * Copyright 1996-2002 by Andruid Kerne. All rights reserved. - * CONFIDENTIAL. Use is subject to license terms. - */ -package ecologylab.collections; - - -/** - * Building block for merge sort implementation. - */ -public interface MergeD -{ -/** - * Descending merge operation for merge sort descending. - * - * @param list1 input, assumed to already be in descending sorted order. - * @param list2 input, assumed to already be in descending sorted order. - * - * @return The 2 {@link DLL DLL}s merged, in descending order. - */ - public DLL mergeDescending(DLL list1, DLL list2); -} +/* + * Copyright 1996-2002 by Andruid Kerne. All rights reserved. + * CONFIDENTIAL. Use is subject to license terms. + */ +package ecologylab.collections; + + +/** + * Building block for merge sort implementation. + */ +public interface MergeD +{ +/** + * Descending merge operation for merge sort descending. + * + * @param list1 input, assumed to already be in descending sorted order. + * @param list2 input, assumed to already be in descending sorted order. + * + * @return The 2 {@link DLL DLL}s merged, in descending order. + */ + public DLL mergeDescending(DLL list1, DLL list2); +} diff --git a/simplCore/src/ecologylab/collections/MultiAncestorScope.java b/simplCore/src/ecologylab/collections/MultiAncestorScope.java deleted file mode 100644 index 2d58b825..00000000 --- a/simplCore/src/ecologylab/collections/MultiAncestorScope.java +++ /dev/null @@ -1,317 +0,0 @@ -package ecologylab.collections; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import ecologylab.generic.StringBuilderBaseUtils; - -/** - * A scope (map: String -> T) with multiple ancestors. - *

- * NOTE that currently this class uses a LRU cache to cache look-ups for values from ancestors for - * efficiency, thus removing a value from an ancestor may not work properly. if you need removing - * please set CACHE_SIZE to zero or modify the class. - * - * @author quyin - * - * @param - * The value type. - */ -@SuppressWarnings({ "serial", "unchecked" }) -public class MultiAncestorScope extends HashMap -{ - - public static int CACHE_SIZE = 16; - - /** - * ancestors of this scope. - */ - private List> ancestors; - - /** - * for caching results from ancestors. - */ - private LinkedHashMap queryCache; - - public MultiAncestorScope() - { - super(); - } - - public MultiAncestorScope(int initialCapacity) - { - super(initialCapacity); - } - - public MultiAncestorScope(int initialCapacity, float loadFactor) - { - super(initialCapacity, loadFactor); - } - - public MultiAncestorScope(Map... ancestors) - { - super(); - this.addAncestors(ancestors); - } - - public MultiAncestorScope(int initialCapacity, Map... ancestors) - { - super(initialCapacity); - this.addAncestors(ancestors); - } - - public MultiAncestorScope(int initialCapacity, float loadFactor, Map... ancestors) - { - super(initialCapacity, loadFactor); - this.addAncestors(ancestors); - } - - /** - * get the value of the given key from this scope. will look up this scope first. if not found, - * look up ancestors one by one, in the order of being added. - */ - @Override - public T get(Object key) - { - HashSet> visited = new HashSet>(); - return getHelper(key, visited); - } - - /** - * helper method that uses a visited hash set to reduce the time complexity of map look-up. - * - * @param key - * @param visited - * @return - */ - private T getHelper(Object key, HashSet> visited) - { - T result = super.get(key); - if (result == null) - result = this.getFromCache(key); - if (result == null) - { - if (this.ancestors != null) - for (Map ancestor : this.ancestors) - if (containsSame(visited, ancestor)) - continue; - else - { - visited.add(ancestor); - if (ancestor instanceof MultiAncestorScope) - result = ((MultiAncestorScope) ancestor).getHelper(key, visited); - else - result = ancestor.get(key); - if (result != null) - { - this.putToCache(key, result); - break; - } - } - } - return result; - } - - private T getFromCache(Object key) - { - return this.queryCache == null ? null : this.queryCache.get(key); - } - - /** - * get a List of values from this scope AND its ancestors. values ordered from near to far. - * - * @param key - * @return - */ - public List getAll(Object key) - { - List results = new ArrayList(); - HashSet> visited = new HashSet>(); - getAllHelper(key, visited, results); - return results; - } - - private void getAllHelper(Object key, HashSet> visited, List results) - { - T result = super.get(key); - if (result != null) - results.add(result); - if (this.ancestors != null) - for (Map ancestor : this.ancestors) - if (containsSame(visited, ancestor)) - continue; - else - { - visited.add(ancestor); - if (ancestor instanceof MultiAncestorScope) - ((MultiAncestorScope) ancestor).getAllHelper(key, visited, results); - else - { - result = ancestor.get(key); - if (result != null) - results.add(result); - } - } - } - - /** - * only put value into the scope when it is not null. this prevents shadowing values with the - * same key in ancestors. - * - * @param key - * @param value - */ - public void putIfValueNotNull(String key, T value) - { - if (value != null) - put(key, value); - } - - private void putToCache(Object key, T value) - { - if (this.queryCache == null) - this.queryCache = new LinkedHashMap() { - @Override - protected boolean removeEldestEntry(java.util.Map.Entry eldest) - { - if (this.size() > CACHE_SIZE) - return true; - return false; - } - }; - this.queryCache.put((String) key, value); - } - - /** - * we need this because the ordinary contains() compares using equals() which is overridden by - * HashMap, thus not meeting our needs. We want to compare using == in some places in this class. - * - * @param - * @param theCollection - * @param theElement - * @return - */ - private static boolean containsSame(Collection theCollection, T theElement) - { - for (T element : theCollection) - if (element == theElement) - return true; - return false; - } - - /** - * - * @return the list of ancestors. - */ - public List> getAncestors() - { - return this.ancestors; - } - - /** - * add an ancestor to (the end of) the ancestor list. - * - * @param ancestor - */ - public void addAncestor(Map ancestor) - { - if (ancestor == null) - return; - if (this.ancestors == null) - this.ancestors = new ArrayList>(); - else if (containsSame(this.ancestors, ancestor)) - return; - this.ancestors.add(ancestor); - if (this.queryCache != null) - this.queryCache.clear(); - } - - /** - * add ancestors to (the end of) the ancestor list. - * - * @param ancestors - */ - public void addAncestors(Map... ancestors) - { - if (ancestors != null) - for (Map ancestor : ancestors) - this.addAncestor(ancestor); - } - - /** - * remove an ancestor from the ancestor list. - * - * @param ancestor - */ - public void removeAncestor(Map ancestor) - { - if (this.ancestors != null) - this.ancestors.remove(ancestor); - if (this.queryCache != null) - this.queryCache.clear(); - } - - @Override - public String toString() - { - StringBuilder sb = StringBuilderBaseUtils.acquire(); - sb.append(this.getClass().getSimpleName()).append("[size: ").append(this.size()).append("]: ") - .append(super.toString()); - - if (this.ancestors != null && this.ancestors.size() > 0) - { - for (Map ancestor : this.ancestors) - { - if (ancestor != null) - { - String ancestorStr = ancestor.toString(); - sb.append("\n\t -> "); - sb.append(ancestorStr.replace("\n", "\n\t")); - } - } - } - - String result = sb.toString(); - StringBuilderBaseUtils.release(sb); - return result; - } - - public void reset() - { - this.ancestors = null; - this.queryCache = null; - this.clear(); - } - - /** - * @param args - */ - public static void main(String[] args) - { - // inheritance relation: - // s1(1, 2) -> s2(3) -> s4(5) - // \-> s3() / - MultiAncestorScope s1 = new MultiAncestorScope(); - s1.put("one", 1); - s1.put("two", 2); - - MultiAncestorScope s2 = new MultiAncestorScope(0, s1); - s2.put("three", 3); - - MultiAncestorScope s3 = new MultiAncestorScope(0, s1); - // s3.put("four", 4); - - MultiAncestorScope s4 = new MultiAncestorScope(0, s2, s3); - s4.put("five", 5); - - System.out.println(s4); - System.out.println(s4.get("five")); - System.out.println(s4.get("two")); - } - -} diff --git a/simplCore/src/ecologylab/collections/OverlappingAnyKeySets.java b/simplCore/src/ecologylab/collections/OverlappingAnyKeySets.java index 6173a451..e59b4df8 100644 --- a/simplCore/src/ecologylab/collections/OverlappingAnyKeySets.java +++ b/simplCore/src/ecologylab/collections/OverlappingAnyKeySets.java @@ -1,121 +1,121 @@ -/** - * - */ -package ecologylab.collections; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class OverlappingAnyKeySets extends - OverlappingSets -{ - Map keyToNumberMapping; - - /** - * - */ - public OverlappingAnyKeySets(K[] keys) - { - super(); - - keyToNumberMapping = new HashMap(); - - long i = 0; - - for (K key : keys) - { - keyToNumberMapping.put(key, ((long) Math.pow(2, i))); - - i++; - } - } - - /** - * @param playerNames - */ - public OverlappingAnyKeySets(List keys) - { - super(); - - keyToNumberMapping = new HashMap(); - - long i = 0; - - for (K key : keys) - { - keyToNumberMapping.put(key, ((long) Math.pow(2, i))); - i++; - } - } - - public void put(K key, O value) - { - super.put(keyToNumberMapping.get(key), value); - } - - public void put(K[] keys, O value) - { - super.put(computeNumericalKey(keys), value); - } - - /** - * @param keys - * @return - */ - private long computeNumericalKey(K[] keys) - { - long numKey = 0; - - for (K key : keys) - { - numKey = numKey | keyToNumberMapping.get(key); - } - return numKey; - } - - public void put(Collection keys, O value) - { - long numKey = 0; - - for (K key : keys) - { - numKey = numKey | keyToNumberMapping.get(key); - } - - super.put(numKey, value); - } - - public List getSet(K... keys) - { - return super.getSet(computeNumericalKey(keys)); - } - - public static void main(String[] args) - { - String[] keys = - { "andruid", "bill", "zach", "ross" }; - - OverlappingAnyKeySets t = new OverlappingAnyKeySets( - keys); - - t.put("andruid", "a"); - t.put(keys, "vowels"); - - String[] t1 = {"zach", "ross"}; - String[] t2 = {"zach", "ross", "andruid"}; - - t.put(t1, "two"); - t.put(t2, "three"); - - t.put(t1, "2"); - t.put(t1, "2two"); - - System.out.println(t.toString()); - } -} +/** + * + */ +package ecologylab.collections; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class OverlappingAnyKeySets extends + OverlappingSets +{ + Map keyToNumberMapping; + + /** + * + */ + public OverlappingAnyKeySets(K[] keys) + { + super(); + + keyToNumberMapping = new HashMap(); + + long i = 0; + + for (K key : keys) + { + keyToNumberMapping.put(key, ((long) Math.pow(2, i))); + + i++; + } + } + + /** + * @param playerNames + */ + public OverlappingAnyKeySets(List keys) + { + super(); + + keyToNumberMapping = new HashMap(); + + long i = 0; + + for (K key : keys) + { + keyToNumberMapping.put(key, ((long) Math.pow(2, i))); + i++; + } + } + + public void put(K key, O value) + { + super.put(keyToNumberMapping.get(key), value); + } + + public void put(K[] keys, O value) + { + super.put(computeNumericalKey(keys), value); + } + + /** + * @param keys + * @return + */ + private long computeNumericalKey(K[] keys) + { + long numKey = 0; + + for (K key : keys) + { + numKey = numKey | keyToNumberMapping.get(key); + } + return numKey; + } + + public void put(Collection keys, O value) + { + long numKey = 0; + + for (K key : keys) + { + numKey = numKey | keyToNumberMapping.get(key); + } + + super.put(numKey, value); + } + + public List getSet(K... keys) + { + return super.getSet(computeNumericalKey(keys)); + } + + public static void main(String[] args) + { + String[] keys = + { "andruid", "bill", "zach", "ross" }; + + OverlappingAnyKeySets t = new OverlappingAnyKeySets( + keys); + + t.put("andruid", "a"); + t.put(keys, "vowels"); + + String[] t1 = {"zach", "ross"}; + String[] t2 = {"zach", "ross", "andruid"}; + + t.put(t1, "two"); + t.put(t2, "three"); + + t.put(t1, "2"); + t.put(t1, "2two"); + + System.out.println(t.toString()); + } +} diff --git a/simplCore/src/ecologylab/collections/OverlappingSets.java b/simplCore/src/ecologylab/collections/OverlappingSets.java index 638f20fd..4624b4fa 100644 --- a/simplCore/src/ecologylab/collections/OverlappingSets.java +++ b/simplCore/src/ecologylab/collections/OverlappingSets.java @@ -1,75 +1,75 @@ -/** - * - */ -package ecologylab.collections; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * A collection of objects that belong to binary categories. Lazilly - * instantiates the necessary intersections of the categories. Maximum - * categories are determined dynamically. Uses bit-masks to indicate container - * relationships. - * - * 63 is the maximum number of binary categories for this class. - * - * Does not allow multiple identical objects in the same set (per the rules of - * Set). - * - * @author Zachary O. Toups (zach@ecologylab.net) - * @author William Hamilton (bill@ecologylab.net) - */ -public class OverlappingSets -{ - /** - * A map of categories to sets of objects contained in them. Keys are bit - * masks indicating the container set. For example, 0001 indicates an object - * is contained only in set 1, 1001 indicates the sets 1 and 4. - */ - private Map> setMap; - - public OverlappingSets() - { - setMap = new HashMap>(); - } - - public List getSet(Long setID) - { - List result = setMap.get(setID); - - if (result == null) - { - synchronized (setMap) - { - result = setMap.get(setID); - - if (result == null) - { - result = new ArrayList(); - - setMap.put(setID, result); - } - } - } - - return result; - } - - public void put(Long setID, O value) - { - List setToInsertInto = getSet(setID); - - setToInsertInto.add(value); - } - - /** - * @see java.lang.Object#toString() - */ - @Override public String toString() - { - return this.setMap.toString(); - } -} +/** + * + */ +package ecologylab.collections; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * A collection of objects that belong to binary categories. Lazilly + * instantiates the necessary intersections of the categories. Maximum + * categories are determined dynamically. Uses bit-masks to indicate container + * relationships. + * + * 63 is the maximum number of binary categories for this class. + * + * Does not allow multiple identical objects in the same set (per the rules of + * Set). + * + * @author Zachary O. Toups (zach@ecologylab.net) + * @author William Hamilton (bill@ecologylab.net) + */ +public class OverlappingSets +{ + /** + * A map of categories to sets of objects contained in them. Keys are bit + * masks indicating the container set. For example, 0001 indicates an object + * is contained only in set 1, 1001 indicates the sets 1 and 4. + */ + private Map> setMap; + + public OverlappingSets() + { + setMap = new HashMap>(); + } + + public List getSet(Long setID) + { + List result = setMap.get(setID); + + if (result == null) + { + synchronized (setMap) + { + result = setMap.get(setID); + + if (result == null) + { + result = new ArrayList(); + + setMap.put(setID, result); + } + } + } + + return result; + } + + public void put(Long setID, O value) + { + List setToInsertInto = getSet(setID); + + setToInsertInto.add(value); + } + + /** + * @see java.lang.Object#toString() + */ + @Override public String toString() + { + return this.setMap.toString(); + } +} diff --git a/simplCore/src/ecologylab/collections/Scope.java b/simplCore/src/ecologylab/collections/Scope.java index 111e0a50..8395d8e7 100644 --- a/simplCore/src/ecologylab/collections/Scope.java +++ b/simplCore/src/ecologylab/collections/Scope.java @@ -1,166 +1,166 @@ -package ecologylab.collections; - -import java.util.HashMap; -import java.util.Map; - -import ecologylab.generic.Debug; - -/** - * A lexical Scope of bindings from names to values. Lexical Scopes can be nested. However, bind - * operations are only performed on the current Scope. Lookup operations chain through parents, as - * necessary, when a binding is not found locally. - */ -public class Scope extends HashMap -{ - protected Map parent; - - /** - * Create a Scope with no parent, using default HashMap size and loadFactor. - */ - public Scope() - { - - } - - /** - * Create a lexical Scope, chained to a parent Scope for resolving lookup/get. Use the default - * HashMap size and loadFactor. - * - * @param parent - */ - public Scope(Map parent) - { - this.parent = parent; - } - - /** - * Create a Scope with no parent, using the specified HashMap size and default loadFactor. - * - * @param size - */ - public Scope(int size) - { - super(size); - } - - /** - * Create a lexical Scope, chained to a parent Scope for resolving lookup/get. Use the specified - * HashMap size and default loadFactor. - * - * @param size - */ - public Scope(Map parent, int size) - { - super(size); - this.parent = parent; - } - - /** - * Create a Scope with no parent, using the specified HashMap size and loadFactor. - * - * @param size - * @param loadFactor - */ - public Scope(int size, float loadFactor) - { - super(size, loadFactor); - } - - /** - * Create a lexical Scope, chained to a parent Scope for resolving lookup/get. Use the specified - * HashMap size and loadFactor. - * - * @param parent - * @param size - * @param loadFactor - */ - public Scope(Map parent, int size, float loadFactor) - { - super(size, loadFactor); - this.parent = parent; - } - - /** - * Lookup an object in this. - * - * @param name - * - * @return The object associated with this name, found in the registry, or null if there is none. - */ - @Override - public T get(Object name) - { - T result = super.get(name); - Map operativeParent = parent; - return (result != null) ? result : ((operativeParent != null) ? operativeParent.get(name) - : null); - } - - /** - * Enable this Scope to inherit bindings from a parent, by setting the parent instance variable in - * this. - * - * @param newParent - */ - public void setParent(Map newParent) - { - Map thisParent = this.parent; - if (thisParent != null) - Debug.warning(this, "Setting parent to " + newParent + " but it was already " + thisParent); - - this.parent = newParent; - } - - /** - * The chained parent Map used for resolving lookup/get operations, if they cannot be resolved in - * this. - * - * @return The parent instance variable in this. - */ - public Map operativeParent() - { - return this.parent; - } - - @Override - public String toString() - { - String parentMsg = (parent == null) ? "" : "\n\t -> " + parent.toString(); - return sizeMsg() + parentMsg; - } - - public String sizeMsg() - { - return "[Scope] w " + size() + " elements. "; - } - - /** - * - * @return A String with all the name value pairs in this, for debugging. - */ - public String dump() - { - StringBuilder result = new StringBuilder(); - result.append("DUMP"); - dump(result, "\t"); - return result.toString(); - } - - private void dump(StringBuilder result, String prefix) - { - result.append('\n').append(prefix).append(sizeMsg()); - dumpThis(result, prefix); - if (parent != null) - ((Scope) parent).dump(result, prefix + "\t"); - } - - public void dumpThis(StringBuilder result, String prefix) - { - for (String key : this.keySet()) - { - result.append(prefix).append(key).append("\t: ").append(get(key)).append('\n'); - } - } - - private static final long serialVersionUID = 5840169416933494011L; -} +package ecologylab.collections; + +import java.util.HashMap; +import java.util.Map; + +import ecologylab.generic.Debug; + +/** + * A lexical Scope of bindings from names to values. Lexical Scopes can be nested. However, bind + * operations are only performed on the current Scope. Lookup operations chain through parents, as + * necessary, when a binding is not found locally. + */ +public class Scope extends HashMap +{ + protected Map parent; + + /** + * Create a Scope with no parent, using default HashMap size and loadFactor. + */ + public Scope() + { + + } + + /** + * Create a lexical Scope, chained to a parent Scope for resolving lookup/get. Use the default + * HashMap size and loadFactor. + * + * @param parent + */ + public Scope(Map parent) + { + this.parent = parent; + } + + /** + * Create a Scope with no parent, using the specified HashMap size and default loadFactor. + * + * @param size + */ + public Scope(int size) + { + super(size); + } + + /** + * Create a lexical Scope, chained to a parent Scope for resolving lookup/get. Use the specified + * HashMap size and default loadFactor. + * + * @param size + */ + public Scope(Map parent, int size) + { + super(size); + this.parent = parent; + } + + /** + * Create a Scope with no parent, using the specified HashMap size and loadFactor. + * + * @param size + * @param loadFactor + */ + public Scope(int size, float loadFactor) + { + super(size, loadFactor); + } + + /** + * Create a lexical Scope, chained to a parent Scope for resolving lookup/get. Use the specified + * HashMap size and loadFactor. + * + * @param parent + * @param size + * @param loadFactor + */ + public Scope(Map parent, int size, float loadFactor) + { + super(size, loadFactor); + this.parent = parent; + } + + /** + * Lookup an object in this. + * + * @param name + * + * @return The object associated with this name, found in the registry, or null if there is none. + */ + @Override + public T get(Object name) + { + T result = super.get(name); + Map operativeParent = parent; + return (result != null) ? result : ((operativeParent != null) ? operativeParent.get(name) + : null); + } + + /** + * Enable this Scope to inherit bindings from a parent, by setting the parent instance variable in + * this. + * + * @param newParent + */ + public void setParent(Map newParent) + { + Map thisParent = this.parent; + if (thisParent != null) + Debug.warning(this, "Setting parent to " + newParent + " but it was already " + thisParent); + + this.parent = newParent; + } + + /** + * The chained parent Map used for resolving lookup/get operations, if they cannot be resolved in + * this. + * + * @return The parent instance variable in this. + */ + public Map operativeParent() + { + return this.parent; + } + + @Override + public String toString() + { + String parentMsg = (parent == null) ? "" : "\n\t -> " + parent.toString(); + return sizeMsg() + parentMsg; + } + + public String sizeMsg() + { + return "[Scope] w " + size() + " elements. "; + } + + /** + * + * @return A String with all the name value pairs in this, for debugging. + */ + public String dump() + { + StringBuilder result = new StringBuilder(); + result.append("DUMP"); + dump(result, "\t"); + return result.toString(); + } + + private void dump(StringBuilder result, String prefix) + { + result.append('\n').append(prefix).append(sizeMsg()); + dumpThis(result, prefix); + if (parent != null) + ((Scope) parent).dump(result, prefix + "\t"); + } + + public void dumpThis(StringBuilder result, String prefix) + { + for (String key : this.keySet()) + { + result.append(prefix).append(key).append("\t: ").append(get(key)).append('\n'); + } + } + + private static final long serialVersionUID = 5840169416933494011L; +} diff --git a/simplCore/src/ecologylab/collections/SetElement.java b/simplCore/src/ecologylab/collections/SetElement.java index 1930aea7..345a303f 100644 --- a/simplCore/src/ecologylab/collections/SetElement.java +++ b/simplCore/src/ecologylab/collections/SetElement.java @@ -1,156 +1,156 @@ -/* - * Copyright 1996-2002 by Andruid Kerne. All rights reserved. CONFIDENTIAL. Use is subject to - * license terms. - */ -package ecologylab.collections; - -import java.util.ArrayList; - -import ecologylab.generic.Debug; - -/** - * A FloatWeightSet element. - * - * Basic implementation of SetElement for cases when you can inherit from here - **/ -public class SetElement extends Debug implements AbstractSetElement -{ - - private boolean recycled = false; - - protected ArrayList sets = null; // new ArrayList(); - - public SetElement() - { - } - - /** - * This can be overridden to exclude elements from selection while keeping them in the set. - * - * @return The default implementation always returns false, including all elements for selection. - */ - public boolean filteredOut() - { - return false; - } - - /** - * Delete in the most expedient manner possible. This is final because you should override - * deleteHook() to provide custom behavior. - */ - @Override - public final void delete() - { - if (!recycled && sets != null) - { - synchronized (sets) - { - for (WeightSet s : sets) - if (s != null) - s.removeFromSet(this); - sets.clear(); - } - } - deleteHook(); - } - - @Override - public void addSet(WeightSet s) - { - if (sets == null && !recycled) - sets = new ArrayList(); - - synchronized (sets) - { - sets.add(s); - } - } - - @Override - public void removeSet(WeightSet s) - { - if (sets != null) - { - synchronized (sets) - { - sets.remove(s); - } - } - } - - /** - * Delete the element from the set. This means changing the set's structure, and also changing - * slots in this to reflect its lack of membership. - * - * @param recompute - * -1 for absolutely no recomputation of the set's internal structures. 0 for recompute - * upwards from el 1 for recompute all - * - * @return true if the element was a member of a set, and thus, if the delete does something; - * false if the element was not a member of a set, and thus, if the delete does *nothing*. - */ - // public final synchronized boolean delete(int recompute) - // { - // boolean inSet = isInSet(); - // if (inSet)//prevent double dip deletes - // { - // set.delete(this, recompute); - // clear(); - // } - // return inSet; - // } - - /** - * Callback that happens at the end of a delete, and when an element gets pruned. This - * implementation is empty. Override to provide custom behaviors. - */ - @Override - public void deleteHook() - { - - } - - /** - * A callback method for when an element is inserted into a floatWeightSet. - * - * This implementation is empty. Override to provide custom behaviors. - */ - @Override - public void insertHook() - { - - } - - @Override - public String toString() - { - return super.toString(); - } - - /** - * Free resources associated w this element. Deletes from all constituent sets. Sets recycled to - * true. - */ - @Override - public void recycle(boolean unconditional) - { - if (!recycled) - { - recycled = true; - delete(); - } - } - - @Override - public boolean recycled() - { - return recycled; - } - - @Override - public boolean isInSet() - { - return (sets != null) && sets.size() > 0; - } - -} +/* + * Copyright 1996-2002 by Andruid Kerne. All rights reserved. CONFIDENTIAL. Use is subject to + * license terms. + */ +package ecologylab.collections; + +import java.util.ArrayList; + +import ecologylab.generic.Debug; + +/** + * A FloatWeightSet element. + * + * Basic implementation of SetElement for cases when you can inherit from here + **/ +public class SetElement extends Debug implements AbstractSetElement +{ + + private boolean recycled = false; + + protected ArrayList sets = null; // new ArrayList(); + + public SetElement() + { + } + + /** + * This can be overridden to exclude elements from selection while keeping them in the set. + * + * @return The default implementation always returns false, including all elements for selection. + */ + public boolean filteredOut() + { + return false; + } + + /** + * Delete in the most expedient manner possible. This is final because you should override + * deleteHook() to provide custom behavior. + */ + @Override + public final void delete() + { + if (!recycled && sets != null) + { + synchronized (sets) + { + for (WeightSet s : sets) + if (s != null) + s.removeFromSet(this); + sets.clear(); + } + } + deleteHook(); + } + + @Override + public void addSet(WeightSet s) + { + if (sets == null && !recycled) + sets = new ArrayList(); + + synchronized (sets) + { + sets.add(s); + } + } + + @Override + public void removeSet(WeightSet s) + { + if (sets != null) + { + synchronized (sets) + { + sets.remove(s); + } + } + } + + /** + * Delete the element from the set. This means changing the set's structure, and also changing + * slots in this to reflect its lack of membership. + * + * @param recompute + * -1 for absolutely no recomputation of the set's internal structures. 0 for recompute + * upwards from el 1 for recompute all + * + * @return true if the element was a member of a set, and thus, if the delete does something; + * false if the element was not a member of a set, and thus, if the delete does *nothing*. + */ + // public final synchronized boolean delete(int recompute) + // { + // boolean inSet = isInSet(); + // if (inSet)//prevent double dip deletes + // { + // set.delete(this, recompute); + // clear(); + // } + // return inSet; + // } + + /** + * Callback that happens at the end of a delete, and when an element gets pruned. This + * implementation is empty. Override to provide custom behaviors. + */ + @Override + public void deleteHook() + { + + } + + /** + * A callback method for when an element is inserted into a floatWeightSet. + * + * This implementation is empty. Override to provide custom behaviors. + */ + @Override + public void insertHook() + { + + } + + @Override + public String toString() + { + return super.toString(); + } + + /** + * Free resources associated w this element. Deletes from all constituent sets. Sets recycled to + * true. + */ + @Override + public void recycle(boolean unconditional) + { + if (!recycled) + { + recycled = true; + delete(); + } + } + + @Override + public boolean recycled() + { + return recycled; + } + + @Override + public boolean isInSet() + { + return (sets != null) && sets.size() > 0; + } + +} diff --git a/simplCore/src/ecologylab/collections/SyncLinkedList.java b/simplCore/src/ecologylab/collections/SyncLinkedList.java index bebeb52c..65652e4e 100644 --- a/simplCore/src/ecologylab/collections/SyncLinkedList.java +++ b/simplCore/src/ecologylab/collections/SyncLinkedList.java @@ -1,164 +1,164 @@ -package ecologylab.collections; - -import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; - -/** - * A synchronized version of {@link java.util.LinkedList LinkedList}, - * because they didn't seem to provided a nice one. - */ -public class SyncLinkedList -implements List -{ - LinkedList list; - - public SyncLinkedList() - { - this(new LinkedList()); - } - public SyncLinkedList(LinkedList list) - { - this.list = list; - } - - @Override - public boolean equals(Object o) { - synchronized(list) {return list.equals(o);} - } - @Override - public int hashCode() { - synchronized(list) {return list.hashCode();} - } - - @Override - public Object get(int index) { - synchronized(list) {return list.get(index);} - } - @Override - public Object set(int index, Object element) { - synchronized(list) {return list.set(index, element);} - } - @Override - public void add(int index, Object element) { - synchronized(list) {list.add(index, element);} - } - public void addFirst(Object o) - { - synchronized(list) {list.addFirst(o);} - } - public void addLast(Object o) - { - synchronized(list) {list.addLast(o);} - } - @Override - public Object remove(int index) { - synchronized(list) {return list.remove(index);} - } - - public Object removeFirst() - { - synchronized(list) {return list.removeFirst();} - } - public Object removeLast() - { - synchronized(list) {return list.removeLast();} - } - public Object getLast() - { - synchronized(list) {return list.getLast();} - } - - @Override - public int indexOf(Object o) { - synchronized(list) {return list.indexOf(o);} - } - @Override - public int lastIndexOf(Object o) { - synchronized(list) {return list.lastIndexOf(o);} - } - - @Override - public boolean addAll(int index, Collection c) { - synchronized(list) {return list.addAll(index, c);} - } - - @Override - public ListIterator listIterator() { - return list.listIterator(); // Must be manually synched by user - } - - @Override - public ListIterator listIterator(int index) { - return list.listIterator(index); // Must be manually synched by usr - } - - @Override - public List subList(int fromIndex, int toIndex) { - synchronized(list) { - return list.subList(fromIndex, toIndex); - } - } - - @Override - public int size() { - synchronized(list) {return list.size();} - } - @Override - public boolean isEmpty() { - synchronized(list) {return list.isEmpty();} - } - @Override - public boolean contains(Object o) { - synchronized(list) {return list.contains(o);} - } - @Override - public Object[] toArray() { - synchronized(list) {return list.toArray();} - } - @Override - public Object[] toArray(Object[] a) { - synchronized(list) {return list.toArray(a);} - } - - @Override - public Iterator iterator() { - return list.iterator(); // Must be manually synched by user! - } - - @Override - public boolean add(Object o) { - synchronized(list) {return list.add(o);} - } - @Override - public boolean remove(Object o) { - synchronized(list) {return list.remove(o);} - } - - @Override - public boolean containsAll(Collection coll) { - synchronized(list) {return list.containsAll(coll);} - } - @Override - public boolean addAll(Collection coll) { - synchronized(list) {return list.addAll(coll);} - } - @Override - public boolean removeAll(Collection coll) { - synchronized(list) {return list.removeAll(coll);} - } - @Override - public boolean retainAll(Collection coll) { - synchronized(list) {return list.retainAll(coll);} - } - @Override - public void clear() { - synchronized(list) {list.clear();} - } - @Override - public String toString() { - synchronized(list) {return list.toString();} - } - } +package ecologylab.collections; + +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +/** + * A synchronized version of {@link java.util.LinkedList LinkedList}, + * because they didn't seem to provided a nice one. + */ +public class SyncLinkedList +implements List +{ + LinkedList list; + + public SyncLinkedList() + { + this(new LinkedList()); + } + public SyncLinkedList(LinkedList list) + { + this.list = list; + } + + @Override + public boolean equals(Object o) { + synchronized(list) {return list.equals(o);} + } + @Override + public int hashCode() { + synchronized(list) {return list.hashCode();} + } + + @Override + public Object get(int index) { + synchronized(list) {return list.get(index);} + } + @Override + public Object set(int index, Object element) { + synchronized(list) {return list.set(index, element);} + } + @Override + public void add(int index, Object element) { + synchronized(list) {list.add(index, element);} + } + public void addFirst(Object o) + { + synchronized(list) {list.addFirst(o);} + } + public void addLast(Object o) + { + synchronized(list) {list.addLast(o);} + } + @Override + public Object remove(int index) { + synchronized(list) {return list.remove(index);} + } + + public Object removeFirst() + { + synchronized(list) {return list.removeFirst();} + } + public Object removeLast() + { + synchronized(list) {return list.removeLast();} + } + public Object getLast() + { + synchronized(list) {return list.getLast();} + } + + @Override + public int indexOf(Object o) { + synchronized(list) {return list.indexOf(o);} + } + @Override + public int lastIndexOf(Object o) { + synchronized(list) {return list.lastIndexOf(o);} + } + + @Override + public boolean addAll(int index, Collection c) { + synchronized(list) {return list.addAll(index, c);} + } + + @Override + public ListIterator listIterator() { + return list.listIterator(); // Must be manually synched by user + } + + @Override + public ListIterator listIterator(int index) { + return list.listIterator(index); // Must be manually synched by usr + } + + @Override + public List subList(int fromIndex, int toIndex) { + synchronized(list) { + return list.subList(fromIndex, toIndex); + } + } + + @Override + public int size() { + synchronized(list) {return list.size();} + } + @Override + public boolean isEmpty() { + synchronized(list) {return list.isEmpty();} + } + @Override + public boolean contains(Object o) { + synchronized(list) {return list.contains(o);} + } + @Override + public Object[] toArray() { + synchronized(list) {return list.toArray();} + } + @Override + public Object[] toArray(Object[] a) { + synchronized(list) {return list.toArray(a);} + } + + @Override + public Iterator iterator() { + return list.iterator(); // Must be manually synched by user! + } + + @Override + public boolean add(Object o) { + synchronized(list) {return list.add(o);} + } + @Override + public boolean remove(Object o) { + synchronized(list) {return list.remove(o);} + } + + @Override + public boolean containsAll(Collection coll) { + synchronized(list) {return list.containsAll(coll);} + } + @Override + public boolean addAll(Collection coll) { + synchronized(list) {return list.addAll(coll);} + } + @Override + public boolean removeAll(Collection coll) { + synchronized(list) {return list.removeAll(coll);} + } + @Override + public boolean retainAll(Collection coll) { + synchronized(list) {return list.retainAll(coll);} + } + @Override + public void clear() { + synchronized(list) {list.clear();} + } + @Override + public String toString() { + synchronized(list) {return list.toString();} + } + } diff --git a/simplCore/src/ecologylab/collections/ValueFactory3.java b/simplCore/src/ecologylab/collections/ValueFactory3.java index 1951eda0..460005f8 100644 --- a/simplCore/src/ecologylab/collections/ValueFactory3.java +++ b/simplCore/src/ecologylab/collections/ValueFactory3.java @@ -1,24 +1,24 @@ -package ecologylab.collections; - - -/** - * Factory for Value objects for hashed data structure with synchronized writes and unsynchronized reads. - - * - * @author andruid @param - * @author andruid @param - * @author andruid @param - * @author andruid @param - */ -public interface ValueFactory3 -{ - /** - * Wrapper for the constructor of type V. - * - * @param key - * @param arg1 - * @param arg2 - * @return - */ - public V createValue(K key, A1 arg1, A2 arg2); -} +package ecologylab.collections; + + +/** + * Factory for Value objects for hashed data structure with synchronized writes and unsynchronized reads. + + * + * @author andruid @param + * @author andruid @param + * @author andruid @param + * @author andruid @param + */ +public interface ValueFactory3 +{ + /** + * Wrapper for the constructor of type V. + * + * @param key + * @param arg1 + * @param arg2 + * @return + */ + public V createValue(K key, A1 arg1, A2 arg2); +} diff --git a/simplCore/src/ecologylab/collections/VectorLA.java b/simplCore/src/ecologylab/collections/VectorLA.java index a05c836e..a8eb09a7 100644 --- a/simplCore/src/ecologylab/collections/VectorLA.java +++ b/simplCore/src/ecologylab/collections/VectorLA.java @@ -1,39 +1,39 @@ -package ecologylab.collections; - -import java.util.Collection; -import java.util.Vector; - -/** - * Linear Access Vector. Extends Vector - * - * - * @param - */ -public class VectorLA extends Vector -implements LinearAccess -{ - - public VectorLA() - { - // TODO Auto-generated constructor stub - } - - public VectorLA(int initialCapacity) - { - super(initialCapacity); - // TODO Auto-generated constructor stub - } - - public VectorLA(Collection c) - { - super(c); - // TODO Auto-generated constructor stub - } - - public VectorLA(int initialCapacity, int capacityIncrement) - { - super(initialCapacity, capacityIncrement); - // TODO Auto-generated constructor stub - } - -} +package ecologylab.collections; + +import java.util.Collection; +import java.util.Vector; + +/** + * Linear Access Vector. Extends Vector + * + * + * @param + */ +public class VectorLA extends Vector +implements LinearAccess +{ + + public VectorLA() + { + // TODO Auto-generated constructor stub + } + + public VectorLA(int initialCapacity) + { + super(initialCapacity); + // TODO Auto-generated constructor stub + } + + public VectorLA(Collection c) + { + super(c); + // TODO Auto-generated constructor stub + } + + public VectorLA(int initialCapacity, int capacityIncrement) + { + super(initialCapacity, capacityIncrement); + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/collections/WeightSet.java b/simplCore/src/ecologylab/collections/WeightSet.java index 6933bac2..03dc7cfa 100644 --- a/simplCore/src/ecologylab/collections/WeightSet.java +++ b/simplCore/src/ecologylab/collections/WeightSet.java @@ -1,465 +1,465 @@ -/* - * Copyright 1996-2002 by Andruid Kerne. All rights reserved. CONFIDENTIAL. Use is subject to - * license terms. - */ -package ecologylab.collections; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Iterator; - -import ecologylab.appframework.Memory; -import ecologylab.generic.ObservableDebug; -import ecologylab.generic.ThreadMaster; - -/** - * Provides the facility of efficient weighted random selection from a set elements, each of whicn - * includes a characterizing floating point weight. - *

- * - * Works in cooperation w SetElements; requiring that user object to keep an integer - * index slot, which only we should be accessing. This impure oo style is an adaption to Java's lack - * of multiple inheritance. - *

- * - * Gotta be careful to be thread safe. Seems no operations can safely occur concurrently. There are - * a bunch of synchronized methods to affect this. - **/ -public class WeightSet extends ObservableDebug implements Iterable, Collection -{ - private static final int NO_MAX_SIZE = -1; - - private final ArrayListX arrayList; - - private final HashSet hashSet; - - private final WeightingStrategy weightingStrategy; - - private final Comparator comparator; - - private int maxSize = NO_MAX_SIZE; - - private static final int DEFAULT_SIZE = 16; - - /** - * This might pause us before we do an expensive operation. - */ - ThreadMaster threadMaster; - - public WeightSet (int maxSize, int initialSize, WeightingStrategy weightingStrategy) - { - assert weightingStrategy != null; - - this.hashSet = new HashSet(initialSize); - this.arrayList = new ArrayListX(initialSize); - this.maxSize = maxSize; - - this.weightingStrategy = weightingStrategy; - this.comparator = new FloatWeightComparator(weightingStrategy); -// for (E e : arrayList) -// weightingStrategy.insert(e); - } - - public WeightSet ( WeightingStrategy getWeightStrategy ) - { - this(NO_MAX_SIZE, DEFAULT_SIZE, getWeightStrategy); - } - - public WeightSet (int maxSize, ThreadMaster threadMaster, WeightingStrategy weightStrategy ) - { - this(maxSize, maxSize, weightStrategy); - this.threadMaster = threadMaster; - } - - // /////////////////////////////////////////////////////// - // DEFAULT COMPARATOR - // /////////////////////////////////////////////////////// - public final class FloatWeightComparator implements Comparator - { - private WeightingStrategy strat; - - public FloatWeightComparator ( WeightingStrategy getWeightStrategy ) - { - strat = getWeightStrategy; - } - - @Override - public int compare ( E o1, E o2 ) - { - return Double.compare(strat.getWeight(o1), strat.getWeight(o2)); - } - }; - - private void sortIfWeShould ( ) - { - // TODO remove this check, make getWeightStrategy call sort? - if (weightingStrategy.hasChanged()) - { - Collections.sort(arrayList, comparator); - setChanged(); - notifyObservers(); - weightingStrategy.clearChanged(); - } - } - - public synchronized double mean ( ) - { - if (arrayList.size() == 0) - return 0; - double mean = 0; - for (E e : arrayList) - mean += weightingStrategy.getWeight(e); - return mean / arrayList.size(); - } - - private synchronized void clearAndRecycle (int start, int end) - { - int size = arrayList.size(); - debug("^^^size before = " + size); - for (int i=end - 1; i>=start; i--) - { - E element = arrayList.get(i); // was remove(i), but that's inefficent - element.deleteHook(); - element.recycle(true);// will also call deleteHook?! - } - // all of these elements are probably at the beginning of the list - // remove from there is worst case behavior of arrayList, because all of the higher elements - // must be moved. - // minimize this by doing it once. - // - // in case of CfContainers, recycle removes them from a set; however a weird case results in - // some of them not being removed, so this makes sure that all recycled elements are removed. - int expectedSize = size - (end - start); - int newSize = arrayList.size(); - if (expectedSize < newSize) - { - int sizeDiff = newSize - expectedSize; - arrayList.removeRange(start, sizeDiff); - } - } - - /** - * Selects the top weighted element from the set.
- * This method removes the selected from the set. - * - * @return - */ - public synchronized E maxSelect ( ) - { - ArrayList list = this.arrayList; - int size = list.size(); - if (size == 0) - return null; - try - { - sortIfWeShould(); - } catch (Throwable t) - { - t.printStackTrace(); - boolean foundNulls = false; - for (int i=list.size() - 1; i>=0; i--) - { - E entry = list.get(i); - if (entry == null) - { - error("Oh my! Null Entry!!!!!"); - list.remove(i); - foundNulls = true; - } - } - if (foundNulls) - return maxSelect(); - } - return list.remove(--size); - } - - public synchronized E maxPeek ( ) - { - ArrayList list = this.arrayList; - int size = list.size(); - if (size == 0) - return null; - sortIfWeShould(); - return list.get(--size); - } - - public synchronized E maxPeek(int index) - { - ArrayList list = this.arrayList; - int size = list.size(); - if (size == 0) - return null; - sortIfWeShould(); - int desiredIndex = size - index - 1; - return list.get(desiredIndex); - } - - /** - * Default implementation of the prune to keep only maxSize elements - */ - public synchronized void prune() - { - prune(maxSize); - } - - public synchronized void prune ( int numToKeep ) - { - if (maxSize < 0) - return; - ArrayList list = this.arrayList; - int numToDelete = list.size() - numToKeep; - if (numToDelete <= 0) - return; - debug("prune() -> "+numToKeep); - sortIfWeShould(); -// List deletionList = list.subList(0, numToDelete); - clearAndRecycle(0, numToDelete); - - Memory.reclaim(); - } - - @Override - public boolean add(E el) - { - return insert(el); - } - - public synchronized boolean insert ( E el ) - { - boolean result = false; - if (!hashSet.contains(el)) - { - weightingStrategy.insert(el); - result |= arrayList.add(el); - hashSet.add(el); - el.addSet(this); - el.insertHook(); - } - return result; - } - - public synchronized boolean remove ( E el ) - { - boolean result = removeFromSet(el); - el.removeSet(this); - return result; - } - - protected synchronized boolean removeFromSet ( E e ) - { - weightingStrategy.remove(e); - boolean result = arrayList.remove(e); - hashSet.remove(e); - return result; - } - - public E get(int i) - { - return arrayList.get(i); - } - /** - * Delete all the elements in the set, as fast as possible. - * - * @param doRecycleElements - * TODO - * - */ - public synchronized void clear ( boolean doRecycleElements ) - { - synchronized (arrayList) - { - for (int i=size()-1; i>0; i--) - { - E e = arrayList.remove(i); - e.deleteHook(); - if (doRecycleElements) - e.recycle(false); - } - arrayList.clear(); - } - hashSet.clear(); - } - - /** - * Prune to the set's specified maxSize, if necessary, then do a maxSelect(). The reason for - * doing these operations together is because both require sorting. - * - * @return element in the set with the highest weight, or in case of a tie, a random pick of - * those. - */ - public synchronized E pruneAndMaxSelect ( ) - { - prune(maxSize); - return maxSelect(); - } - - @Override - public int size ( ) - { - return arrayList.size(); - } - - @Override - public String toString ( ) - { - return super.toString() + "[" + size() + "]"; - } - - /** - * Check to see if the set has any elements. - * - * @return - */ - @Override - public boolean isEmpty ( ) - { - return size() == 0; - } - - /** - * Fetches the i'th element in the sorted list. - * - * @param i - * index into the list - * @return the element at index i - */ - public synchronized E at ( int i ) - { - ArrayList list = this.arrayList; - if (list.size() == 0 || i >= list.size()) - return null; - sortIfWeShould(); - return list.get(i); - } - - /** - * Fetches the weight of the i'th element in the sorted list. - * - * @param i - * index into the list - * @return the weight of the element at index i - */ - public synchronized Double weightAt ( int i ) - { - ArrayList list = this.arrayList; - if (list.size() == 0) - return null; - sortIfWeShould(); - - return weightingStrategy.getWeight(list.get(i)); - } - - - /** - * Fetches the highest weight in this set - * @return - */ - public synchronized Double maxWeight() - { - return weightAt(this.arrayList.size() - 1); - } - - /** - * Fetches the weight of the passed in element. - * - * @param e - * Element to weigh. Doesn't have to be a member of the set. - * @return the weight of the element - */ - public double getWeight ( E e ) - { - return weightingStrategy.getWeight(e); - } - /** - * Method Overriden by {@link cf.model.VisualPool VisualPool} to return true - * - * @return - */ - public boolean isRunnable ( ) - { - return false; - } - - public WeightingStrategy getWeightStrategy ( ) - { - return weightingStrategy; - } - - @Override - public synchronized Iterator iterator ( ) - { - return arrayList.iterator(); - } - - @Override - public boolean addAll(Collection arg0) - { - boolean result = false; - for (E element: arg0) - result |= add(element); - return result; - } - - @Override - public void clear() - { - clear(false); - } - - @Override - public boolean contains(Object arg0) - { - // TODO Auto-generated method stub - return hashSet.contains(arg0); - } - - @Override - public boolean containsAll(Collection arg0) - { - throw new RuntimeException("not implemented."); - } - - @Override - public boolean remove(Object arg0) - { - return remove((E) arg0); - } - - @Override - public boolean removeAll(Collection arg0) - { - boolean result = false; - for (Object o : arg0) - result |= remove(o); - return result; - } - - @Override - public boolean retainAll(Collection arg0) - { - throw new RuntimeException("not implemented."); - } - - @Override - public Object[] toArray() - { - return arrayList.toArray(); - } - - @Override - public T[] toArray(T[] arg0) - { - return arrayList.toArray(arg0); - } - - public void toArray(E[] arg0, int start) - { - int pos = start; - for (int i = 0; i < size(); i++) - arg0[pos++] = arrayList.get(i); - } - -} +/* + * Copyright 1996-2002 by Andruid Kerne. All rights reserved. CONFIDENTIAL. Use is subject to + * license terms. + */ +package ecologylab.collections; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; + +import ecologylab.appframework.Memory; +import ecologylab.generic.ObservableDebug; +import ecologylab.generic.ThreadMaster; + +/** + * Provides the facility of efficient weighted random selection from a set elements, each of whicn + * includes a characterizing floating point weight. + *

+ * + * Works in cooperation w SetElements; requiring that user object to keep an integer + * index slot, which only we should be accessing. This impure oo style is an adaption to Java's lack + * of multiple inheritance. + *

+ * + * Gotta be careful to be thread safe. Seems no operations can safely occur concurrently. There are + * a bunch of synchronized methods to affect this. + **/ +public class WeightSet extends ObservableDebug implements Iterable, Collection +{ + private static final int NO_MAX_SIZE = -1; + + private final ArrayListX arrayList; + + private final HashSet hashSet; + + private final WeightingStrategy weightingStrategy; + + private final Comparator comparator; + + private int maxSize = NO_MAX_SIZE; + + private static final int DEFAULT_SIZE = 16; + + /** + * This might pause us before we do an expensive operation. + */ + ThreadMaster threadMaster; + + public WeightSet (int maxSize, int initialSize, WeightingStrategy weightingStrategy) + { + assert weightingStrategy != null; + + this.hashSet = new HashSet(initialSize); + this.arrayList = new ArrayListX(initialSize); + this.maxSize = maxSize; + + this.weightingStrategy = weightingStrategy; + this.comparator = new FloatWeightComparator(weightingStrategy); +// for (E e : arrayList) +// weightingStrategy.insert(e); + } + + public WeightSet ( WeightingStrategy getWeightStrategy ) + { + this(NO_MAX_SIZE, DEFAULT_SIZE, getWeightStrategy); + } + + public WeightSet (int maxSize, ThreadMaster threadMaster, WeightingStrategy weightStrategy ) + { + this(maxSize, maxSize, weightStrategy); + this.threadMaster = threadMaster; + } + + // /////////////////////////////////////////////////////// + // DEFAULT COMPARATOR + // /////////////////////////////////////////////////////// + public final class FloatWeightComparator implements Comparator + { + private WeightingStrategy strat; + + public FloatWeightComparator ( WeightingStrategy getWeightStrategy ) + { + strat = getWeightStrategy; + } + + @Override + public int compare ( E o1, E o2 ) + { + return Double.compare(strat.getWeight(o1), strat.getWeight(o2)); + } + }; + + private void sortIfWeShould ( ) + { + // TODO remove this check, make getWeightStrategy call sort? + if (weightingStrategy.hasChanged()) + { + Collections.sort(arrayList, comparator); + setChanged(); + notifyObservers(); + weightingStrategy.clearChanged(); + } + } + + public synchronized double mean ( ) + { + if (arrayList.size() == 0) + return 0; + double mean = 0; + for (E e : arrayList) + mean += weightingStrategy.getWeight(e); + return mean / arrayList.size(); + } + + private synchronized void clearAndRecycle (int start, int end) + { + int size = arrayList.size(); + debug("^^^size before = " + size); + for (int i=end - 1; i>=start; i--) + { + E element = arrayList.get(i); // was remove(i), but that's inefficent + element.deleteHook(); + element.recycle(true);// will also call deleteHook?! + } + // all of these elements are probably at the beginning of the list + // remove from there is worst case behavior of arrayList, because all of the higher elements + // must be moved. + // minimize this by doing it once. + // + // in case of CfContainers, recycle removes them from a set; however a weird case results in + // some of them not being removed, so this makes sure that all recycled elements are removed. + int expectedSize = size - (end - start); + int newSize = arrayList.size(); + if (expectedSize < newSize) + { + int sizeDiff = newSize - expectedSize; + arrayList.removeRange(start, sizeDiff); + } + } + + /** + * Selects the top weighted element from the set.
+ * This method removes the selected from the set. + * + * @return + */ + public synchronized E maxSelect ( ) + { + ArrayList list = this.arrayList; + int size = list.size(); + if (size == 0) + return null; + try + { + sortIfWeShould(); + } catch (Throwable t) + { + t.printStackTrace(); + boolean foundNulls = false; + for (int i=list.size() - 1; i>=0; i--) + { + E entry = list.get(i); + if (entry == null) + { + error("Oh my! Null Entry!!!!!"); + list.remove(i); + foundNulls = true; + } + } + if (foundNulls) + return maxSelect(); + } + return list.remove(--size); + } + + public synchronized E maxPeek ( ) + { + ArrayList list = this.arrayList; + int size = list.size(); + if (size == 0) + return null; + sortIfWeShould(); + return list.get(--size); + } + + public synchronized E maxPeek(int index) + { + ArrayList list = this.arrayList; + int size = list.size(); + if (size == 0) + return null; + sortIfWeShould(); + int desiredIndex = size - index - 1; + return list.get(desiredIndex); + } + + /** + * Default implementation of the prune to keep only maxSize elements + */ + public synchronized void prune() + { + prune(maxSize); + } + + public synchronized void prune ( int numToKeep ) + { + if (maxSize < 0) + return; + ArrayList list = this.arrayList; + int numToDelete = list.size() - numToKeep; + if (numToDelete <= 0) + return; + debug("prune() -> "+numToKeep); + sortIfWeShould(); +// List deletionList = list.subList(0, numToDelete); + clearAndRecycle(0, numToDelete); + + Memory.reclaim(); + } + + @Override + public boolean add(E el) + { + return insert(el); + } + + public synchronized boolean insert ( E el ) + { + boolean result = false; + if (!hashSet.contains(el)) + { + weightingStrategy.insert(el); + result |= arrayList.add(el); + hashSet.add(el); + el.addSet(this); + el.insertHook(); + } + return result; + } + + public synchronized boolean remove ( E el ) + { + boolean result = removeFromSet(el); + el.removeSet(this); + return result; + } + + protected synchronized boolean removeFromSet ( E e ) + { + weightingStrategy.remove(e); + boolean result = arrayList.remove(e); + hashSet.remove(e); + return result; + } + + public E get(int i) + { + return arrayList.get(i); + } + /** + * Delete all the elements in the set, as fast as possible. + * + * @param doRecycleElements + * TODO + * + */ + public synchronized void clear ( boolean doRecycleElements ) + { + synchronized (arrayList) + { + for (int i=size()-1; i>0; i--) + { + E e = arrayList.remove(i); + e.deleteHook(); + if (doRecycleElements) + e.recycle(false); + } + arrayList.clear(); + } + hashSet.clear(); + } + + /** + * Prune to the set's specified maxSize, if necessary, then do a maxSelect(). The reason for + * doing these operations together is because both require sorting. + * + * @return element in the set with the highest weight, or in case of a tie, a random pick of + * those. + */ + public synchronized E pruneAndMaxSelect ( ) + { + prune(maxSize); + return maxSelect(); + } + + @Override + public int size ( ) + { + return arrayList.size(); + } + + @Override + public String toString ( ) + { + return super.toString() + "[" + size() + "]"; + } + + /** + * Check to see if the set has any elements. + * + * @return + */ + @Override + public boolean isEmpty ( ) + { + return size() == 0; + } + + /** + * Fetches the i'th element in the sorted list. + * + * @param i + * index into the list + * @return the element at index i + */ + public synchronized E at ( int i ) + { + ArrayList list = this.arrayList; + if (list.size() == 0 || i >= list.size()) + return null; + sortIfWeShould(); + return list.get(i); + } + + /** + * Fetches the weight of the i'th element in the sorted list. + * + * @param i + * index into the list + * @return the weight of the element at index i + */ + public synchronized Double weightAt ( int i ) + { + ArrayList list = this.arrayList; + if (list.size() == 0) + return null; + sortIfWeShould(); + + return weightingStrategy.getWeight(list.get(i)); + } + + + /** + * Fetches the highest weight in this set + * @return + */ + public synchronized Double maxWeight() + { + return weightAt(this.arrayList.size() - 1); + } + + /** + * Fetches the weight of the passed in element. + * + * @param e + * Element to weigh. Doesn't have to be a member of the set. + * @return the weight of the element + */ + public double getWeight ( E e ) + { + return weightingStrategy.getWeight(e); + } + /** + * Method Overriden by {@link cf.model.VisualPool VisualPool} to return true + * + * @return + */ + public boolean isRunnable ( ) + { + return false; + } + + public WeightingStrategy getWeightStrategy ( ) + { + return weightingStrategy; + } + + @Override + public synchronized Iterator iterator ( ) + { + return arrayList.iterator(); + } + + @Override + public boolean addAll(Collection arg0) + { + boolean result = false; + for (E element: arg0) + result |= add(element); + return result; + } + + @Override + public void clear() + { + clear(false); + } + + @Override + public boolean contains(Object arg0) + { + // TODO Auto-generated method stub + return hashSet.contains(arg0); + } + + @Override + public boolean containsAll(Collection arg0) + { + throw new RuntimeException("not implemented."); + } + + @Override + public boolean remove(Object arg0) + { + return remove((E) arg0); + } + + @Override + public boolean removeAll(Collection arg0) + { + boolean result = false; + for (Object o : arg0) + result |= remove(o); + return result; + } + + @Override + public boolean retainAll(Collection arg0) + { + throw new RuntimeException("not implemented."); + } + + @Override + public Object[] toArray() + { + return arrayList.toArray(); + } + + @Override + public T[] toArray(T[] arg0) + { + return arrayList.toArray(arg0); + } + + public void toArray(E[] arg0, int start) + { + int pos = start; + for (int i = 0; i < size(); i++) + arg0[pos++] = arrayList.get(i); + } + +} diff --git a/simplCore/src/ecologylab/collections/WeightingStrategy.java b/simplCore/src/ecologylab/collections/WeightingStrategy.java index 89bdae08..96225ed2 100644 --- a/simplCore/src/ecologylab/collections/WeightingStrategy.java +++ b/simplCore/src/ecologylab/collections/WeightingStrategy.java @@ -1,34 +1,34 @@ -package ecologylab.collections; - -import ecologylab.generic.Debug; - -public abstract class WeightingStrategy extends Debug -{ - private boolean changed; - - public abstract double getWeight(E e); - - public void insert(E e) { - setChanged(); - }; - - public void remove(E e) { - setChanged(); - }; - - public boolean hasChanged() { - return changed; - } - - public void setChanged() { - synchronized(this) { - changed = true; - } - } - - public void clearChanged() { - synchronized(this) { - changed = false; - } - } -} +package ecologylab.collections; + +import ecologylab.generic.Debug; + +public abstract class WeightingStrategy extends Debug +{ + private boolean changed; + + public abstract double getWeight(E e); + + public void insert(E e) { + setChanged(); + }; + + public void remove(E e) { + setChanged(); + }; + + public boolean hasChanged() { + return changed; + } + + public void setChanged() { + synchronized(this) { + changed = true; + } + } + + public void clearChanged() { + synchronized(this) { + changed = false; + } + } +} diff --git a/simplCore/src/ecologylab/collections/package.html b/simplCore/src/ecologylab/collections/package.html index 3781b8de..b6082291 100644 --- a/simplCore/src/ecologylab/collections/package.html +++ b/simplCore/src/ecologylab/collections/package.html @@ -1,3 +1,3 @@ - -Objects for managing collections. - + +Objects for managing collections. + diff --git a/simplCore/src/ecologylab/concurrent/BasicSite.java b/simplCore/src/ecologylab/concurrent/BasicSite.java index 45698638..1fc772ac 100644 --- a/simplCore/src/ecologylab/concurrent/BasicSite.java +++ b/simplCore/src/ecologylab/concurrent/BasicSite.java @@ -12,231 +12,285 @@ import ecologylab.serialization.types.element.IMappable; /** - * * - * @author andruid + * @author andruid */ - @simpl_tag("site") -public -class BasicSite extends ElementState implements IMappable +public class BasicSite extends ElementState implements IMappable, Site { - - static Random random = new Random(System.currentTimeMillis()); - - @simpl_scalar protected String domain; - @simpl_scalar - int numTimeouts; + static Random random = new Random(System.currentTimeMillis()); + + @simpl_scalar + protected String domain; + + @simpl_scalar + private int maxDownloaders; - @simpl_scalar - int numFileNotFounds; + @simpl_scalar + int numTimeouts; - @simpl_scalar - int numOtherIoErrors; + @simpl_scalar + int numFileNotFounds; - @simpl_scalar - int numNormalDownloads; + @simpl_scalar + int numOtherIoErrors; - protected int downloadsQueuedOrInProgress; + @simpl_scalar + int numNormalDownloads; - boolean ignore; - - long nextAvailableTime; - - static final int MAX_TIMEOUTS = 6; + protected int downloadsQueuedOrInProgress; + + boolean ignore; + + long nextAvailableTime; + + static final int MAX_TIMEOUTS = 6; /** - * Minimum time to wait between downloads for this domain - * Specified in seconds + * Minimum time to wait between downloads for this domain Specified in seconds */ - @simpl_scalar protected float minDownloadInterval; - - + @simpl_scalar + protected float minDownloadInterval; + /** * Timestamp of last download from this site; */ - long lastDownloadAt; - - @simpl_scalar protected boolean ignoreSemanticBoost; - - boolean isDownloading; - - /** - * Use for XML Translation - */ - public BasicSite() - { - // TODO Auto-generated constructor stub - } - - public void countTimeout(ParsedURL location) - { - numTimeouts++; - warning("Timeout " + numTimeouts + "\t" + location); - } - - public void countFileNotFound(ParsedURL location) - { - numFileNotFounds++; - warning("FileNotFound " + numFileNotFounds + "\t" + location); - } - - public void countOtherIoError(ParsedURL location) - { - numOtherIoErrors++; - warning("Other IO Error " + numOtherIoErrors + "\t" + location); - } - - public void countNormalDownload() - { - numNormalDownloads++; - } - - public synchronized void queuedDownload() - { - downloadsQueuedOrInProgress++; - } - - public synchronized void endDownload() - { - debug("Ending downloading for site"); - isDownloading = false; - downloadsQueuedOrInProgress--; - } - - - public boolean tooManyTimeouts() - { - return numTimeouts >= MAX_TIMEOUTS; - } - - public boolean isDown() - { - boolean result = tooManyTimeouts(); - if (result) - warning("Cancelling because " + numTimeouts + " timeouts"); - return result; - } - - /** - * - * @return (numTimeouts == 0) ? 1 : 1.0 / (numTimeouts + 1); - */ - public double timeoutsFactor() - { - return (numTimeouts == 0) ? 1 : 1.0 / (numTimeouts + 1); - } - - /** - * @return the minDownloadInterval - */ - public float getMinDownloadInterval() - { - return minDownloadInterval; - } - - /** - * @param minDownloadInterval the minDownloadInterval to set - */ - public void setMinDownloadInterval(float minDownloadInterval) - { - this.minDownloadInterval = minDownloadInterval; - } - - /** - * @return the lastDownloadAt - */ - public long getLastDownloadAt() - { - return lastDownloadAt; - } - - /** - * Register that we are down loading, and the current time as when the down load started. - */ - public void beginActualDownload() - { - this.isDownloading = true; - this.lastDownloadAt = System.currentTimeMillis(); - } - - /** - * Swing delays between downloads for a site by a large margin. - * @return time in millis - */ - public long getDecentDownloadInterval() - { - int millis = (int) (minDownloadInterval * 1000); - return millis + random.nextInt(millis / 2); - } - public boolean constrainDownloadInterval() - { - return minDownloadInterval > 0; - } - @Override - public String key() - { - return domain; - } - - /** - * - * - * @return the isDownloading - */ - public boolean isDownloading() - { - return isDownloading; - } - - /** - * Call this when a download to a site was actually fulfilled by a local copy. - */ - public void resetLastDownloadAt() - { - this.lastDownloadAt = 0; - } - - public String domain() - { - return domain; - } - - public boolean ignoreSemanticBoost() - { - return ignoreSemanticBoost; - } - - public boolean shouldIgnore() - { - return ignore; - } - - /** - * Recycle and Mark this site as recycled. - * - */ - public void setIgnored(boolean ignore) - { - this.ignore = ignore; - } - + long lastDownloadAt; + + @simpl_scalar + protected boolean ignoreSemanticBoost; + + boolean isDownloading; + + /** + * Use for XML Translation + */ + public BasicSite() + { + // TODO Auto-generated constructor stub + } + + @Override + public void countTimeout(ParsedURL location) + { + numTimeouts++; + warning("Timeout " + numTimeouts + "\t" + location); + } + + @Override + public void countFileNotFound(ParsedURL location) + { + numFileNotFounds++; + warning("FileNotFound " + numFileNotFounds + "\t" + location); + } + + @Override + public void countOtherIoError(ParsedURL location) + { + numOtherIoErrors++; + warning("Other IO Error " + numOtherIoErrors + "\t" + location); + } + + @Override + public void countNormalDownload(ParsedURL location) + { + numNormalDownloads++; + } + + @Override + public synchronized void queueDownload(ParsedURL location) + { + downloadsQueuedOrInProgress++; + } + + @Override + public synchronized void endDownload(ParsedURL location) + { + debug("Ending downloading for site"); + isDownloading = false; + downloadsQueuedOrInProgress--; + } + + public boolean tooManyTimeouts() + { + return numTimeouts >= MAX_TIMEOUTS; + } + + @Override + public boolean isDown() + { + boolean result = tooManyTimeouts(); + if (result) + warning("Cancelling because " + numTimeouts + " timeouts"); + return result; + } + + /** + * + * @return (numTimeouts == 0) ? 1 : 1.0 / (numTimeouts + 1); + */ + public double timeoutsFactor() + { + return (numTimeouts == 0) ? 1 : 1.0 / (numTimeouts + 1); + } + + /** + * @return the minDownloadInterval + */ + public float getMinDownloadInterval() + { + return minDownloadInterval; + } + + /** + * @param minDownloadInterval + * the minDownloadInterval to set + */ + public void setMinDownloadInterval(float minDownloadInterval) + { + this.minDownloadInterval = minDownloadInterval; + } + + /** + * @return the lastDownloadAt + */ + @Override + public long getLastDownloadAt() + { + return lastDownloadAt; + } + + /** + * Register that we are down loading, and the current time as when the down load started. + */ + @Override + public void beginDownload(ParsedURL location) + { + this.isDownloading = true; + this.lastDownloadAt = System.currentTimeMillis(); + } + + @Override + public long getDownloadInterval() + { + return (long) (minDownloadInterval * 1000); + } + + /** + * Swing delays between downloads for a site by a large margin. + * + * @return time in millis + */ + @Override + public long getDecentDownloadInterval() + { + int millis = (int) (minDownloadInterval * 1000); + return millis + random.nextInt(millis / 2); + } + + @Override + public boolean isDownloadingConstrained() + { + return minDownloadInterval > 0; + } + + @Override + public String key() + { + return domain; + } + + /** + * + * + * @return the isDownloading + */ + @Override + public boolean isDownloading() + { + return isDownloading; + } + + /** + * Call this when a download to a site was actually fulfilled by a local copy. + */ + public void resetLastDownloadAt() + { + this.lastDownloadAt = 0; + } + + @Override + public String domain() + { + return domain; + } + + public boolean ignoreSemanticBoost() + { + return ignoreSemanticBoost; + } + + @Override + public boolean isIgnored() + { + return ignore; + } + + /** + * Recycle and Mark this site as recycled. + * + */ + @Override + public void setIgnored(boolean ignore) + { + this.ignore = ignore; + } + + @Override public long getNextAvailableTime() - { - return nextAvailableTime; - } + { + return nextAvailableTime; + } + + @Override + public void advanceNextAvailableTime() + { + this.nextAvailableTime = System.currentTimeMillis() + getDecentDownloadInterval(); + } + + @Override + public int getMaxDownloaders() + { + return maxDownloaders; + } + + private static final int TWELVE_HOURS_IN_MILLIS = 1000 * 60 * 60 * 12; + + @Override + public void setAbnormallyLongNextAvailableTime() + { + this.nextAvailableTime = System.currentTimeMillis() + TWELVE_HOURS_IN_MILLIS; + } + + public int numOfNormalDownloads() + { + return numNormalDownloads; + } - void advanceNextAvailableTime() - { - this.nextAvailableTime = System.currentTimeMillis() + getDecentDownloadInterval(); - } + public int numOfTimeouts() + { + return numTimeouts; + } - private static final int TWELVE_HOURS_IN_MILLIS = 1000*60*60*12; + public int numOfNotFounds() + { + return numFileNotFounds; + } - public void setAbnormallyLongNextAvailableTime() - { - this.nextAvailableTime = System.currentTimeMillis() + TWELVE_HOURS_IN_MILLIS; - } + public int numOfOtherIoError() + { + return numOtherIoErrors; + } } diff --git a/simplCore/src/ecologylab/concurrent/BatchDownload.java b/simplCore/src/ecologylab/concurrent/BatchDownload.java index 4b058f55..6978f6db 100644 --- a/simplCore/src/ecologylab/concurrent/BatchDownload.java +++ b/simplCore/src/ecologylab/concurrent/BatchDownload.java @@ -1,201 +1,201 @@ -package ecologylab.concurrent; - -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.Observable; - -import ecologylab.generic.Continuation; - -public class BatchDownload extends Observable implements Continuation -{ - /** - * Where the Downloadables are placed after download. - * The key can be arbitrary and is not used during download. It IS - * respected and will be maintained across downloads for later - * identification. - */ - Hashtable finalDownloadables; - - /** - * The number of total downloads that SHOULD be performed. - */ - int totalNumDownloads; - - /** - * The number of downloads that have COMPLETED. - */ - int numberDownloadsSuccessful = 0; - - /** - * The number of downloads that failed and will NOT be attempted again. - */ - int numberDownloadsFailed = 0; - - DownloadMonitor downloadMonitor; - - String batchName = "Batch Downloader"; - - /** - * Number of threads to use for downloading these Downloadables - */ - int numDownloadThreads; - - /** - * HashMap of downloadables keyed with an arbitrary index. - */ - HashMap downloadables; - - /** - * An inverted index of downloadables used to map the delivered Downloadable object - * to its key when building the finalDownloadables Hashtable. - */ - HashMap invertedIndexDownloadables; - - boolean firstRun = true; - - /** - * @param batchName The name that identifies this batch of downloads. Used - * to name the DownloadMonitor. - * @param numDownloadThreads The number of threads to use for simultaneous downloads. - */ - public BatchDownload(String batchName, int numDownloadThreads) - { - this.batchName = batchName; - this.numDownloadThreads = numDownloadThreads; - - downloadMonitor = new DownloadMonitor(batchName, numDownloadThreads); - } - - /** - * Set the hash map of downloadables that will be downloaded on start. - * - * @param downloadables A HashMap of identifier keys mapped to Downloadables for download - */ - public void setDownloads(HashMap downloadables) - { - //free previous resources (if any), but don't kill the download monitor. - freeResources(false); - - numberDownloadsFailed = 0; - numberDownloadsSuccessful = 0; - - this.downloadables = new HashMap(downloadables); - totalNumDownloads = downloadables.size(); - finalDownloadables = new Hashtable(totalNumDownloads); - invertedIndexDownloadables = new HashMap(totalNumDownloads); - - // build the downloadables inverted index for fast lookup based on - //the Downloadable object. - Iterator it = downloadables.keySet().iterator(); - while (it.hasNext()) - { - Object key = it.next(); - Object value = downloadables.get(key); - invertedIndexDownloadables.put(value, key); - } - } - - /** - * Begin downloading each page and retrieving it's content. - */ - public void startDownloads() - { - Iterator urlIterator = downloadables.keySet().iterator(); - while (urlIterator.hasNext()) - { - Downloadable downloadable = (Downloadable) downloadables - .get(urlIterator.next()); - downloadMonitor.download(downloadable, this); - } - - /* - if (!firstRun) - { - System.out.println("starting downloads manually!"); - downloadMonitor.performDownloads(); - System.out.println("finished blocking at performDownloads()"); - } - firstRun = false; - */ - } - - @Override - public void callback(Object o) - { - if (o == null) - { - System.err.println("Null download delivery"); - notifyObserversIfFinished(); - numberDownloadsFailed++; - return; - } - - numberDownloadsSuccessful++; - - Downloadable downloadable = (Downloadable) o; - Object originalKey = invertedIndexDownloadables.get(downloadable); - - finalDownloadables.put(originalKey, downloadable); - notifyObserversIfFinished(); - } - - public boolean isDone() - { - return ((numberDownloadsFailed + numberDownloadsSuccessful) == totalNumDownloads); - } - - protected void notifyObserversIfFinished() - { - if (isDone()) - { - setChanged(); - notifyObservers(); - } - } - - public Hashtable getDownloads() - { - return finalDownloadables; - } - - /** - * Free any resources associated with instantiating and using this object. - * This is only necessary to attempt to minimize how much time elapses - * before this object is garbage collected after use and nullification. - * - * @param freeDownloadMonitor Whether or not to stop and clear the download monitor. - */ - protected void freeResources(boolean freeDownloadMonitor) - { - if (finalDownloadables != null) - { - finalDownloadables.clear(); - finalDownloadables = null; - } - - if (downloadables != null) - { - downloadables.clear(); - downloadables = null; - } - - if (invertedIndexDownloadables != null) - { - invertedIndexDownloadables.clear(); - invertedIndexDownloadables = null; - } - - if (freeDownloadMonitor && downloadMonitor != null) - { - downloadMonitor.stop(); - downloadMonitor = null; - } - } - - public void freeResources() - { - freeResources(true); - } - -} +package ecologylab.concurrent; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Observable; + +import ecologylab.generic.Continuation; + +public class BatchDownload extends Observable implements Continuation +{ + /** + * Where the Downloadables are placed after download. + * The key can be arbitrary and is not used during download. It IS + * respected and will be maintained across downloads for later + * identification. + */ + Hashtable finalDownloadables; + + /** + * The number of total downloads that SHOULD be performed. + */ + int totalNumDownloads; + + /** + * The number of downloads that have COMPLETED. + */ + int numberDownloadsSuccessful = 0; + + /** + * The number of downloads that failed and will NOT be attempted again. + */ + int numberDownloadsFailed = 0; + + DownloadMonitor downloadMonitor; + + String batchName = "Batch Downloader"; + + /** + * Number of threads to use for downloading these Downloadables + */ + int numDownloadThreads; + + /** + * HashMap of downloadables keyed with an arbitrary index. + */ + HashMap downloadables; + + /** + * An inverted index of downloadables used to map the delivered Downloadable object + * to its key when building the finalDownloadables Hashtable. + */ + HashMap invertedIndexDownloadables; + + boolean firstRun = true; + + /** + * @param batchName The name that identifies this batch of downloads. Used + * to name the DownloadMonitor. + * @param numDownloadThreads The number of threads to use for simultaneous downloads. + */ + public BatchDownload(String batchName, int numDownloadThreads) + { + this.batchName = batchName; + this.numDownloadThreads = numDownloadThreads; + + downloadMonitor = new DownloadMonitor(batchName, numDownloadThreads); + } + + /** + * Set the hash map of downloadables that will be downloaded on start. + * + * @param downloadables A HashMap of identifier keys mapped to Downloadables for download + */ + public void setDownloads(HashMap downloadables) + { + //free previous resources (if any), but don't kill the download monitor. + freeResources(false); + + numberDownloadsFailed = 0; + numberDownloadsSuccessful = 0; + + this.downloadables = new HashMap(downloadables); + totalNumDownloads = downloadables.size(); + finalDownloadables = new Hashtable(totalNumDownloads); + invertedIndexDownloadables = new HashMap(totalNumDownloads); + + // build the downloadables inverted index for fast lookup based on + //the Downloadable object. + Iterator it = downloadables.keySet().iterator(); + while (it.hasNext()) + { + Object key = it.next(); + Object value = downloadables.get(key); + invertedIndexDownloadables.put(value, key); + } + } + + /** + * Begin downloading each page and retrieving it's content. + */ + public void startDownloads() + { + Iterator urlIterator = downloadables.keySet().iterator(); + while (urlIterator.hasNext()) + { + Downloadable downloadable = (Downloadable) downloadables + .get(urlIterator.next()); + downloadMonitor.download(downloadable, this); + } + + /* + if (!firstRun) + { + System.out.println("starting downloads manually!"); + downloadMonitor.performDownloads(); + System.out.println("finished blocking at performDownloads()"); + } + firstRun = false; + */ + } + + @Override + public void callback(Object o) + { + if (o == null) + { + System.err.println("Null download delivery"); + notifyObserversIfFinished(); + numberDownloadsFailed++; + return; + } + + numberDownloadsSuccessful++; + + Downloadable downloadable = (Downloadable) o; + Object originalKey = invertedIndexDownloadables.get(downloadable); + + finalDownloadables.put(originalKey, downloadable); + notifyObserversIfFinished(); + } + + public boolean isDone() + { + return ((numberDownloadsFailed + numberDownloadsSuccessful) == totalNumDownloads); + } + + protected void notifyObserversIfFinished() + { + if (isDone()) + { + setChanged(); + notifyObservers(); + } + } + + public Hashtable getDownloads() + { + return finalDownloadables; + } + + /** + * Free any resources associated with instantiating and using this object. + * This is only necessary to attempt to minimize how much time elapses + * before this object is garbage collected after use and nullification. + * + * @param freeDownloadMonitor Whether or not to stop and clear the download monitor. + */ + protected void freeResources(boolean freeDownloadMonitor) + { + if (finalDownloadables != null) + { + finalDownloadables.clear(); + finalDownloadables = null; + } + + if (downloadables != null) + { + downloadables.clear(); + downloadables = null; + } + + if (invertedIndexDownloadables != null) + { + invertedIndexDownloadables.clear(); + invertedIndexDownloadables = null; + } + + if (freeDownloadMonitor && downloadMonitor != null) + { + downloadMonitor.stop(); + downloadMonitor = null; + } + } + + public void freeResources() + { + freeResources(true); + } + +} diff --git a/simplCore/src/ecologylab/concurrent/DownloadEvent.java b/simplCore/src/ecologylab/concurrent/DownloadEvent.java new file mode 100644 index 00000000..5b622d52 --- /dev/null +++ b/simplCore/src/ecologylab/concurrent/DownloadEvent.java @@ -0,0 +1,20 @@ +package ecologylab.concurrent; + +import ecologylab.logging.LogEvent; +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * When a Downloadable is downloaded. + * + * @author quyin + */ +@simpl_inherit +public class DownloadEvent extends LogEvent +{ + + public DownloadEvent() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/concurrent/DownloadMonitor.java b/simplCore/src/ecologylab/concurrent/DownloadMonitor.java index 33591f5d..795797ad 100644 --- a/simplCore/src/ecologylab/concurrent/DownloadMonitor.java +++ b/simplCore/src/ecologylab/concurrent/DownloadMonitor.java @@ -1,782 +1,823 @@ -package ecologylab.concurrent; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.SocketTimeoutException; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Vector; - -import ecologylab.appframework.Memory; -import ecologylab.appframework.OutOfMemoryErrorHandler; -import ecologylab.appframework.StatusReporter; -import ecologylab.generic.Continuation; -import ecologylab.generic.Debug; -import ecologylab.generic.Generic; -import ecologylab.generic.MathTools; -import ecologylab.generic.NewPorterStemmer; -import ecologylab.io.DownloadProcessor; - -/** - * Non-linear flow multiplexer. Tracks downloads of Downloadable objects. Dispatches - * downloaded media to the appropriate DispatchTarget. - *

- * Looks out for timeout conditions. In case they happen, records state in the bad - * slot, and dispatches, as well. - */ -public class DownloadMonitor extends Monitor implements - DownloadProcessor -{ - static HashMap stemmersHash = new HashMap(); - - // ////////////////// queues for media that gets downloaded ///////////////// - /** - * This is the queue of DownloadClosures waiting to be downloaded. - */ - private Vector toDownload = new Vector(30); - - static final int NO_SLEEP = 0; - static final int REGULAR_SLEEP = 400; - static final int SHORT_SLEEP = 100; - static final int LOW_MEMORY_SLEEP = 3000; - static final int LOW_MEMORY_THRESHOLD = 2 * Memory.DANGER_THRESHOLD; - - int dispatched; - private int pending; - private boolean paused; - - /** - * Settable variable reduces sleep between downloads to speed up collecting (SHORT_SLEEP). - * - */ - private boolean hurry; - private boolean dontWait; - private Thread[] downloadThreads; - private int[] priorities; - private int numDownloadThreads; - private String name; - private StatusReporter status; - - // ////////////////// queues for media that gets downloaded ///////////////// - - protected boolean finished; - private static ThreadGroup THREAD_GROUP = new ThreadGroup("DownloadMonitor"); - - private int lowPriority; - private int midPriority; - private int highPriority; - - private final int highThreshold; - private final int midThreshold; - - public static final int HIGHER_PRIORITY = 4; - public static final int HIGH_PRIORITY = 3; - public static final int MID_PRIORITY = 2; - public static final int LOW_PRIORITY = 1; - public static final int MAX_WAIT_TIME = 1000; - private static final int MAX_WAIT_WHEN_PAUSED = 5000; - - - private final Object TOO_MANY_PENDING_LOCK = new Object(); - - private boolean stopRequested = false; - - public DownloadMonitor(String name, int numDownloadThreads) - { - this(name, numDownloadThreads, 0); - } - - public DownloadMonitor(String name, int numDownloadThreads, int priorityBoost) - { - this.numDownloadThreads = numDownloadThreads; - this.name = name; - - highThreshold = numDownloadThreads * 2; - midThreshold = numDownloadThreads + 1; - finished = false; - - lowPriority = LOW_PRIORITY + priorityBoost; - midPriority = MID_PRIORITY + priorityBoost; - highPriority = HIGH_PRIORITY + priorityBoost; - } - - // ----------------------- perform downloads ------------------------------// - /** - * Entry point for Downloadables that want to be downloaded by 1 of our - * performDownload() threads. Starts the performDownload() threads, if necessary. - *

- * After performDownload() is called on the Downloadable, then in the normal case, downloadDone() - * is called, and then the DispatchTarget is called. In the error case, handleIOError() or - * handleTimeout() is called. - */ - @Override - public void download(T thatDownloadable, Continuation continuation) - { - synchronized (toDownload) - { - BasicSite site = thatDownloadable.getDownloadSite(); - if (site != null) - site.queuedDownload(); - - DownloadableLogRecord logRecord = thatDownloadable.getLogRecord(); - - debug("\n download("+thatDownloadable.getDownloadLocation() + ")"); - toDownload.add(new DownloadState(thatDownloadable, continuation, this)); - - if (logRecord != null) - logRecord.setEnQueueTimestamp(System.currentTimeMillis()); - - if (downloadThreads == null) - startPerformDownloadsThreads(); - else - toDownload.notify(); - } - } - - /** - * Cancel a download that has been queued, but not yet started. - * - * @param thatDownloadable - */ - public void cancelDownload(Downloadable thatDownloadable) - { - synchronized (toDownload) - { - for (DownloadState dc : toDownload) - { - if (dc.downloadable.equals(thatDownloadable)) - { - toDownload.remove(dc); - break; - } - } - } - } - - /** - * Set the priority of the download thread. The more backed up we are, the higher the priority. - * - * @param t - * @return - */ - private int setDownloadPriority() - { - return setDownloadPriority(Thread.currentThread()); - } - - /** - * Set the priority of the download thread. The more backed up we are, the higher the priority. - * - * @param t - * @return - */ - private int setDownloadPriority(Thread t) - { - int waiting = toDownload.size(); - int priority; - - if (waiting >= midThreshold) - priority = midPriority; - else if (waiting >= highThreshold) - priority = midPriority; - else - priority = lowPriority; - - Generic.setPriority(t, priority); - - return priority; - } - - /** - * Create a new Thread that runs performDownloads(). - * - * @param i - * @return - */ - protected Thread newPerformDownloadsThread(int i) - { - return newPerformDownloadsThread(i, ""); - } - - /** - * Create a new Thread that runs performDownloads(). - * - * @param i - * @param s - * @return - */ - protected Thread newPerformDownloadsThread(int i, String s) - { - return new Thread(THREAD_GROUP, toString() + "-download " + i + " " + s) - { - @Override - public void run() - { - performDownloads(); - } - }; - } - - /** - * Creates and starts up our performDownloads() Threads. - * - */ - private void startPerformDownloadsThreads() - { - if (downloadThreads == null) - { - finished = false; - downloadThreads = new Thread[numDownloadThreads]; - priorities = new int[numDownloadThreads]; - for (int i = 0; i < numDownloadThreads; i++) - { - Thread thatThread = newPerformDownloadsThread(i); - downloadThreads[i] = thatThread; - thatThread.setPriority(lowPriority); - priorities[i] = lowPriority; - // ThreadDebugger.registerMyself(thatThread); - thatThread.start(); - } - } - } - - public void pause(int sleepTime) - { - pause(true); - Generic.sleep(sleepTime); - unpause(); - } - - public void pause() - { - pause(true); - } - - public void unpause() - { - if (paused) - { - pause(false); - notifyAll(toDownload); - } - } - - public void pause(boolean paused) - { - synchronized (toDownload) - { - // debug("pause("+paused); - this.paused = paused; - - int[] priorities = this.priorities; // avoid race - if (paused) - { - if (downloadThreads != null) - { - for (int i = 0; i < numDownloadThreads; i++) - { - Thread thatThread = downloadThreads[i]; - if (thatThread != null) - { - int thatPriority = thatThread.getPriority(); - priorities[i] = thatPriority; - if (Thread.MIN_PRIORITY < thatPriority) - thatThread.setPriority(Thread.MIN_PRIORITY); - } - } - } - } - else - { - if (downloadThreads != null) - { - for (int i = 0; i < numDownloadThreads; i++) - { - // restore priorities - Thread t = downloadThreads[i]; - if ((t != null) && (priorities != null) && t.isAlive()) - { - // debug("restore priority to " + priorities[i]); - int thatPriority = priorities[i]; - if (thatPriority <= 0) - thatPriority = 1; - t.setPriority(thatPriority); - } - } - } - } - } - } - - /** - * Keep track of system millis that this site can be hit at. - */ - // this state moved into BasicSite! andruid 8/23/11 -// public static Hashtable siteTimeTable = new Hashtable(); - /** - * The heart of the workhorse Threads. It loops, pulling a DownloadClosure off the toDownload - * queue, calling its performDownload() method, and then calling dispatch() if there is a - * dispatchTarget. - * - * - */ - void performDownloads() - { - Thread downloadThread = Thread.currentThread(); - while (!finished) // major sleep at the bottom - { - // keep track if local file to avoid wait - boolean isLocalFile = false; - - DownloadState thatClosure = null; // define out here to use outside of synchronized - Downloadable downloadable = null; - synchronized (toDownload) - { - // debug("-- got lock"); - if (paused) - wait(toDownload, MAX_WAIT_WHEN_PAUSED); - if (toDownload.isEmpty()) - wait(toDownload, MAX_WAIT_TIME); - if (finished) - break; - - // Let's assume that the change in time while iterating over toDownload doesn't matter. - // We don't want to hit this method for every item. - final long currentTimeMillis = System.currentTimeMillis(); - int closureNum = 0; - final int toDownloadSize = toDownloadSize(); - if (toDownloadSize > 0) - { - boolean recycleClosure = false; - while (closureNum < toDownloadSize) - { - recycleClosure = false; - thatClosure = toDownload.get(closureNum); - downloadable = thatClosure.downloadable; - - DownloadableLogRecord logRecord = downloadable.getLogRecord(); - if (logRecord != null) - logRecord.addQueuePeekInterval( - System.currentTimeMillis() - logRecord.getEnQueueTimestamp()); - - if (downloadable.isCached()) - { - if (logRecord != null) logRecord.setHtmlCacheHit(true); - debug("downloadable cached, skip site checking and download intervals"); - break; - } - - BasicSite site = downloadable.getDownloadSite(); - if(site != null && site.shouldIgnore()) - { - recycleClosure = true; - break; - } - - if (site != null && site.constrainDownloadInterval() && !downloadable.isImage()) - { - Long nextDownloadableAt = site.getNextAvailableTime(); // siteTimeTable.get(site); - if(nextDownloadableAt != null) - { - long timeRemaining = nextDownloadableAt - currentTimeMillis; - if (timeRemaining < 0 ) - { - if(thatClosure.shouldCancel() && !downloadable.isRecycled()) - { - recycleClosure = true; - break; - } - debug("\t\t-- Downloading: " + downloadable + " at\t" + new Date(currentTimeMillis) + " --"); - site.advanceNextAvailableTime(); -// setNextAvailableTimeForSite(site); - break; - } - else // Its not time yet, so skip this downloadable. - { - // debug("Ignoring downloadable: " + thatClosure.downloadable + ". need atleast another: " - // + ((float) timeRemaining / 1000.0) + " seconds"); - thatClosure = null; - } - } - else - { - // No nextDownloadableAt time found for this site, - //put in a new value, and accept this downloadClosure - site.advanceNextAvailableTime(); - break; - } - } - else if (site != null && site.isDownloading()) - { // Another one from this site is already downloading, so skip this downloadable. - thatClosure = null; - } - else if (!thatClosure.shouldCancel()) - { - // Site-less downloadables - isLocalFile = downloadable.getDownloadLocation().isFile(); - break; - } - closureNum++; - thatClosure = null; - } // end while - - if (thatClosure != null) - { - // We have a satisfactory downloadClosure, ready to be downloaded. - - toDownload.remove(closureNum); - if(recycleClosure) - { - //Set Site recycled flag to true, - // ignore containers that might be already queued in the DownloadMonitor. - debug(" Recycling downloadable : " + downloadable); - thatClosure.recycle(true); - } - //System.out.println("Download Queue after this download:"); - } - } - } // end synchronized - - boolean lowMemory = Memory.reclaimIfLow(); - - if (thatClosure != null) - { - synchronized (TOO_MANY_PENDING_LOCK) - { - if (!this.highNumberWaiting()) - TOO_MANY_PENDING_LOCK.notifyAll(); - } - if (lowMemory) - { - if (status != null) - status.display("Running out of memory, so not downloading new files.", 6); - toDownload.insertElementAt(thatClosure, 0); // put it back into the queue - } - else - { - try - { - synchronized (nonePendingLock) - { - pending++; - } - - // ThreadDebugger.waitIfPaused(downloadThread); - // NEW -- set the priority of the download, based on how backed up we are - setDownloadPriority(); - thatClosure.performDownload(); // HERE! - } - catch (SocketTimeoutException e) - { - BasicSite site = downloadable.getDownloadSite(); - if (site != null) - site.countTimeout(downloadable.getDownloadLocation()); - downloadable.handleIoError(e); - } - catch (FileNotFoundException e) - { - BasicSite site = downloadable.getDownloadSite(); - if (site != null) - site.countFileNotFound(downloadable.getDownloadLocation()); - downloadable.handleIoError(e); - } - catch (IOException e) - { - BasicSite site = downloadable.getDownloadSite(); - if (site != null) - site.countOtherIoError(downloadable.getDownloadLocation()); - downloadable.handleIoError(e); - } - catch (ThreadDeath e) - { - debug("ThreadDeath in performDownloads() loop"); - e.printStackTrace(); - throw e; - } -// catch (ClosedByInterruptException e) -// { -// debug("Recovering from ClosedByInterruptException in performDownloads() loop."); -// e.printStackTrace(); -// thatClosure.handleIoError(); -// } - catch (OutOfMemoryError e) - { - finished = true; // give up! - downloadable.handleIoError(e); - OutOfMemoryErrorHandler.handleException(e); - - } - catch (Throwable e) - { - String interruptedStr = Thread.interrupted() ? " interrupted" : ""; - debugA("performDownloads() -- recovering from " + interruptedStr + " exception on " - + thatClosure + ":"); - e.printStackTrace(); - downloadable.handleIoError(e); - } - finally - { - synchronized (nonePendingLock) - { - pending--; - notifyAll(nonePendingLock); - } - - BasicSite site = downloadable.getDownloadSite(); - if (site != null) - site.endDownload(); - - thatClosure.callContinuation(); // always call the continuation, error or not! - thatClosure.recycle(false); - } - } - } - - int sleepTime = dontWait || isLocalFile ? NO_SLEEP - : (lowMemory ? LOW_MEMORY_SLEEP - : (hurry ? SHORT_SLEEP - : (REGULAR_SLEEP + MathTools.random(100)))); -// debug("\t\t-------\tSleeping for: " + sleepTime); - Generic.sleep(sleepTime); - - if (stopRequested && isIdle()) - break; - } // while (!finished) - debug("exiting -- " + Thread.currentThread()); - } - - @Override - public String toString() - { - return super.toString() + "[" + name + "]"; - } - - @Override - public void stop() - { - stop(false); - } - - /** - * Stop our threads. - */ - public void stop(boolean kill) - { - // debug("stop()"); - finished = true; - - notifyAll(toDownload); - - if (downloadThreads != null) - { - for (int i = 0; i < downloadThreads.length; i++) - { - Thread thatThread = downloadThreads[i]; - if (kill) - thatThread.stop(); - downloadThreads[i] = null; - } - downloadThreads = null; - } - } - - public int waitingToDownload() - { - return toDownload.size(); - } - - /** - * @return true if we're backed up with unresloved downloads. - */ - public boolean highNumberWaiting() - { - return toDownload.size() > highThreshold; - } - - public boolean midNumberWaiting() - { - return toDownload.size() > midThreshold; - } - - public int lowPriority() - { - return lowPriority; - } - - public int midPriority() - { - return midPriority; - } - - public int highPriority() - { - return highPriority; - } - - public int pending() - { - return pending; - } - - public final Object nonePendingLock = new Object(); - - public void waitUntilNonePending() - { - synchronized (nonePendingLock) - { - while (pending > 0) - { - wait(nonePendingLock); - } - } - } - - /** - * Set whether or not this download monitor needs to wait after each download attempt - * @param noWait - */ - public void setNoWait(boolean noWait) - { - dontWait = noWait; - } - - public void setHurry(boolean hurry) - { - this.hurry = hurry; - debug("setHurry(" + hurry); - } - - public static NewPorterStemmer getStemmer() - { - Thread currentThread = Thread.currentThread(); - NewPorterStemmer stemmer = stemmersHash.get(currentThread); - if (stemmer == null) - { - stemmer = new NewPorterStemmer(); - stemmersHash.put(currentThread, stemmer); - } - return stemmer; - } - - /** - * check the number of elements in the toDownload Queue - * - * @return - */ - public int toDownloadSize() - { - return toDownload.size(); - } - - /** - * Stop performing downloads, and then Get rid of queued DownloadClosures. - */ - public void clear() - { - pause(); - toDownload.clear(); - } - - public void waitIfTooManyPending() - { - if (!highNumberWaiting()) - return; - synchronized (TOO_MANY_PENDING_LOCK) - { - try - { - debug("wait() on TOO_MANY_PENDING_LOCK"); - printQueue(); - TOO_MANY_PENDING_LOCK.wait(); - debug("finished wait() on TOO_MANY_PENDING_LOCK"); - } - catch (InterruptedException e) - { - Debug.weird(this, "Interrupted while waiting for TOO_MANY_PENDING_LOCK"); - e.printStackTrace(); - } - } - } - - public void printQueue() - { - synchronized (toDownload) - { - System.out.println(this.toString() + "QUEUE:"); - for (DownloadState d : toDownload) - { - System.out.println("\t" + d.downloadable); - } - } - System.out.println("\n"); - } - - public StatusReporter getStatus() - { - return status; - } - - public void setStatus(StatusReporter status) - { - this.status = status; - } - - /** - * Removes all downloadClosures that come from this site. - * @param site - */ - public void removeAllDownloadClosuresFromSite(BasicSite site) - { - synchronized(toDownload) - { - ArrayList indexesToRemove = new ArrayList(); - int index = 0; - for(DownloadState d : toDownload) - if(d.downloadable != null && d.downloadable.getDownloadSite() == site) - indexesToRemove.add(index++); - if(indexesToRemove.size() > 0) - { - debug("Removing " + indexesToRemove.size() + " from the queue"); - for(int removeIndex : indexesToRemove) - toDownload.remove(removeIndex); - } - else - debug("Nothing to remove for site: " + site); - } - } - - /** - * @return the paused - */ - public boolean isPaused() - { - return paused; - } - - public int size() - { - return toDownloadSize(); - } - - /** - * check if the monitor is in idle state -- no downloads in the queue nor pending for dispatching. - * - * @return - */ - public boolean isIdle() - { - return pending() == 0 && toDownloadSize() == 0; - } - - /** - * this will cause the main loop (performDownloads()) stops after isIdle() == true. (after sleeping for some time) - * - */ - @Override - public void requestStop() - { - stopRequested = true; - } - -} +package ecologylab.concurrent; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Vector; + +import ecologylab.appframework.Memory; +import ecologylab.appframework.OutOfMemoryErrorHandler; +import ecologylab.appframework.StatusReporter; +import ecologylab.generic.Continuation; +import ecologylab.generic.Debug; +import ecologylab.generic.Generic; +import ecologylab.generic.MathTools; +import ecologylab.generic.NewPorterStemmer; +import ecologylab.io.DownloadProcessor; +import ecologylab.logging.LogEventTypeScope; + +/** + * Non-linear flow multiplexer. Tracks downloads of Downloadable objects. Dispatches + * downloaded media to the appropriate DispatchTarget. + *

+ * Looks out for timeout conditions. In case they happen, records state in the bad + * slot, and dispatches, as well. + */ +public class DownloadMonitor extends Monitor implements + DownloadProcessor +{ + + static HashMap stemmersHash = new HashMap(); + + static + { + LogEventTypeScope.addEventClass(EnqueueEvent.class); + LogEventTypeScope.addEventClass(QueuePeekEvent.class); + } + + // ////////////////// queues for media that gets downloaded ///////////////// + /** + * This is the queue of DownloadClosures waiting to be downloaded. + */ + private Vector toDownload = new Vector(30); + + static final int NO_SLEEP = 0; + static final int REGULAR_SLEEP = 400; + static final int SHORT_SLEEP = 100; + static final int LOW_MEMORY_SLEEP = 3000; + static final int LOW_MEMORY_THRESHOLD = 2 * Memory.DANGER_THRESHOLD; + + int dispatched; + private int pending; + private boolean paused; + + /** + * Settable variable reduces sleep between downloads to speed up collecting (SHORT_SLEEP). + * + */ + private boolean hurry; + private boolean dontWait; + private Thread[] downloadThreads; + private int[] priorities; + private int numDownloadThreads; + private String name; + private StatusReporter status; + + // ////////////////// queues for media that gets downloaded ///////////////// + + protected boolean finished; + private static ThreadGroup THREAD_GROUP = new ThreadGroup("DownloadMonitor"); + + private int lowPriority; + private int midPriority; + private int highPriority; + + private final int highThreshold; + private final int midThreshold; + + public static final int HIGHER_PRIORITY = 4; + public static final int HIGH_PRIORITY = 3; + public static final int MID_PRIORITY = 2; + public static final int LOW_PRIORITY = 1; + public static final int MAX_WAIT_TIME = 1000; + private static final int MAX_WAIT_WHEN_PAUSED = 5000; + + + private final Object TOO_MANY_PENDING_LOCK = new Object(); + + private boolean stopRequested = false; + + public DownloadMonitor(String name, int numDownloadThreads) + { + this(name, numDownloadThreads, 0); + } + + public DownloadMonitor(String name, int numDownloadThreads, int priorityBoost) + { + this.numDownloadThreads = numDownloadThreads; + this.name = name; + + highThreshold = numDownloadThreads * 2; + midThreshold = numDownloadThreads + 1; + finished = false; + + lowPriority = LOW_PRIORITY + priorityBoost; + midPriority = MID_PRIORITY + priorityBoost; + highPriority = HIGH_PRIORITY + priorityBoost; + } + + // ----------------------- perform downloads ------------------------------// + /** + * Entry point for Downloadables that want to be downloaded by 1 of our + * performDownload() threads. Starts the performDownload() threads, if necessary. + *

+ * After performDownload() is called on the Downloadable, then in the normal case, downloadDone() + * is called, and then the DispatchTarget is called. In the error case, handleIOError() or + * handleTimeout() is called. + */ + @Override + public void download(T thatDownloadable, Continuation continuation) + { + synchronized (toDownload) + { + Site site = thatDownloadable.getDownloadSite(); + if (site != null) + site.queueDownload(thatDownloadable.getDownloadLocation()); + + DownloadableLogRecord logRecord = thatDownloadable.getLogRecord(); + + debug("\n download("+thatDownloadable.getDownloadLocation() + ")"); + toDownload.add(new DownloadState(thatDownloadable, continuation, this)); + + if (logRecord != null) + logRecord.addEnqueueEvent(); + + if (downloadThreads == null) + startPerformDownloadsThreads(); + else + toDownload.notify(); + } + } + + /** + * Download the given downloadable, and return a Future object. When calling the get() method on + * the Future object, the thread will block until the downloading is done. + * + * @param downloadable + * @return + */ + public DownloadMonitorResult downloadAndWait(T downloadable) + { + DownloadMonitorResult result = new DownloadMonitorResult(this, downloadable); + download(downloadable, result); + return result; + } + + /** + * Cancel a download that has been queued, but not yet started. + * + * @param thatDownloadable + */ + public void cancelDownload(Downloadable thatDownloadable) + { + synchronized (toDownload) + { + for (DownloadState dc : toDownload) + { + if (dc.downloadable.equals(thatDownloadable)) + { + toDownload.remove(dc); + break; + } + } + } + } + + /** + * Set the priority of the download thread. The more backed up we are, the higher the priority. + * + * @param t + * @return + */ + private int setDownloadPriority() + { + return setDownloadPriority(Thread.currentThread()); + } + + /** + * Set the priority of the download thread. The more backed up we are, the higher the priority. + * + * @param t + * @return + */ + private int setDownloadPriority(Thread t) + { + int waiting = toDownload.size(); + int priority; + + if (waiting >= midThreshold) + priority = midPriority; + else if (waiting >= highThreshold) + priority = midPriority; + else + priority = lowPriority; + + Generic.setPriority(t, priority); + + return priority; + } + + /** + * Create a new Thread that runs performDownloads(). + * + * @param i + * @return + */ + protected Thread newPerformDownloadsThread(int i) + { + return newPerformDownloadsThread(i, ""); + } + + /** + * Create a new Thread that runs performDownloads(). + * + * @param i + * @param s + * @return + */ + protected Thread newPerformDownloadsThread(int i, String s) + { + return new Thread(THREAD_GROUP, toString() + "-download " + i + " " + s) + { + @Override + public void run() + { + performDownloads(); + } + }; + } + + /** + * Creates and starts up our performDownloads() Threads. + * + */ + private void startPerformDownloadsThreads() + { + if (downloadThreads == null) + { + finished = false; + downloadThreads = new Thread[numDownloadThreads]; + priorities = new int[numDownloadThreads]; + for (int i = 0; i < numDownloadThreads; i++) + { + Thread thatThread = newPerformDownloadsThread(i); + downloadThreads[i] = thatThread; + thatThread.setPriority(lowPriority); + priorities[i] = lowPriority; + // ThreadDebugger.registerMyself(thatThread); + thatThread.start(); + } + } + } + + public void pause(int sleepTime) + { + pause(true); + Generic.sleep(sleepTime); + unpause(); + } + + public void pause() + { + pause(true); + } + + public void unpause() + { + if (paused) + { + pause(false); + notifyAll(toDownload); + } + } + + public void pause(boolean paused) + { + synchronized (toDownload) + { + // debug("pause("+paused); + this.paused = paused; + + int[] priorities = this.priorities; // avoid race + if (paused) + { + if (downloadThreads != null) + { + for (int i = 0; i < numDownloadThreads; i++) + { + Thread thatThread = downloadThreads[i]; + if (thatThread != null) + { + int thatPriority = thatThread.getPriority(); + priorities[i] = thatPriority; + if (Thread.MIN_PRIORITY < thatPriority) + thatThread.setPriority(Thread.MIN_PRIORITY); + } + } + } + } + else + { + if (downloadThreads != null) + { + for (int i = 0; i < numDownloadThreads; i++) + { + // restore priorities + Thread t = downloadThreads[i]; + if ((t != null) && (priorities != null) && t.isAlive()) + { + // debug("restore priority to " + priorities[i]); + int thatPriority = priorities[i]; + if (thatPriority <= 0) + thatPriority = 1; + t.setPriority(thatPriority); + } + } + } + } + } + } + + /** + * Keep track of system millis that this site can be hit at. + */ + // this state moved into BasicSite! andruid 8/23/11 +// public static Hashtable siteTimeTable = new Hashtable(); + /** + * The heart of the workhorse Threads. It loops, pulling a DownloadClosure off the toDownload + * queue, calling its performDownload() method, and then calling dispatch() if there is a + * dispatchTarget. + * + * + */ + void performDownloads() + { + Thread downloadThread = Thread.currentThread(); + while (!finished) // major sleep at the bottom + { + // keep track if local file to avoid wait + boolean isLocalFile = false; + + DownloadState thatClosure = null; // define out here to use outside of synchronized + Downloadable downloadable = null; + DownloadableLogRecord logRecord = null; + + synchronized (toDownload) + { + // debug("-- got lock"); + if (paused) + wait(toDownload, MAX_WAIT_WHEN_PAUSED); + if (toDownload.isEmpty()) + wait(toDownload, MAX_WAIT_TIME); + if (finished) + break; + + // Let's assume that the change in time while iterating over toDownload doesn't matter. + // We don't want to hit this method for every item. + final long currentTimeMillis = System.currentTimeMillis(); + int closureNum = 0; + final int toDownloadSize = toDownloadSize(); + if (toDownloadSize > 0) + { + boolean recycleClosure = false; + while (closureNum < toDownloadSize) + { + recycleClosure = false; + thatClosure = toDownload.get(closureNum); + downloadable = thatClosure.downloadable; + logRecord = downloadable.getLogRecord(); + + if (logRecord != null) + { + logRecord.addQueuePeekEvent(); + } + + if (downloadable.isCached()) + { + debug("downloadable cached, skip site checking and download intervals"); + break; + } + + Site site = downloadable.getDownloadSite(); + if(site != null && site.isIgnored()) + { + recycleClosure = true; + break; + } + + if (site != null && site.isDownloadingConstrained() && !downloadable.isImage()) + { + Long nextDownloadableAt = site.getNextAvailableTime(); // siteTimeTable.get(site); + if(nextDownloadableAt != null) + { + long timeRemaining = nextDownloadableAt - currentTimeMillis; + if (timeRemaining < 0 ) + { + if(thatClosure.shouldCancel() && !downloadable.isRecycled()) + { + recycleClosure = true; + break; + } + debug("\t\t-- Downloading: " + downloadable + " at\t" + new Date(currentTimeMillis) + " --"); + site.advanceNextAvailableTime(); +// setNextAvailableTimeForSite(site); + break; + } + else // Its not time yet, so skip this downloadable. + { + // debug("Ignoring downloadable: " + thatClosure.downloadable + ". need atleast another: " + // + ((float) timeRemaining / 1000.0) + " seconds"); + thatClosure = null; + } + } + else + { + // No nextDownloadableAt time found for this site, + //put in a new value, and accept this downloadClosure + site.advanceNextAvailableTime(); + break; + } + } + else if (site != null && site.isDownloading()) + { // Another one from this site is already downloading, so skip this downloadable. + thatClosure = null; + } + else if (!thatClosure.shouldCancel()) + { + // Site-less downloadables + isLocalFile = downloadable.getDownloadLocation().isFile(); + break; + } + closureNum++; + thatClosure = null; + } // end while + + if (thatClosure != null) + { + // We have a satisfactory downloadClosure, ready to be downloaded. + + toDownload.remove(closureNum); + if(recycleClosure) + { + //Set Site recycled flag to true, + // ignore containers that might be already queued in the DownloadMonitor. + debug(" Recycling downloadable : " + downloadable); + thatClosure.recycle(true); + } + //System.out.println("Download Queue after this download:"); + } + } + } // end synchronized + + boolean lowMemory = reclaimMemoryIfLow(); + + if (thatClosure != null) + { + synchronized (TOO_MANY_PENDING_LOCK) + { + if (!this.highNumberWaiting()) + TOO_MANY_PENDING_LOCK.notifyAll(); + } + if (lowMemory) + { + if (status != null) + status.display("Running out of memory, so not downloading new files.", 6); + toDownload.insertElementAt(thatClosure, 0); // put it back into the queue + } + else + { + try + { + synchronized (nonePendingLock) + { + pending++; + } + + // ThreadDebugger.waitIfPaused(downloadThread); + // NEW -- set the priority of the download, based on how backed up we are + setDownloadPriority(); + thatClosure.performDownload(); // HERE! + if (logRecord != null) + { + logRecord.addDownloadEvent(); + } + } + catch (SocketTimeoutException e) + { + Site site = downloadable.getDownloadSite(); + if (site != null) + site.countTimeout(downloadable.getDownloadLocation()); + downloadable.handleIoError(e); + } + catch (FileNotFoundException e) + { + Site site = downloadable.getDownloadSite(); + if (site != null) + site.countFileNotFound(downloadable.getDownloadLocation()); + downloadable.handleIoError(e); + } + catch (IOException e) + { + Site site = downloadable.getDownloadSite(); + if (site != null) + site.countOtherIoError(downloadable.getDownloadLocation()); + downloadable.handleIoError(e); + } + catch (ThreadDeath e) + { + debug("ThreadDeath in performDownloads() loop"); + e.printStackTrace(); + throw e; + } +// catch (ClosedByInterruptException e) +// { +// debug("Recovering from ClosedByInterruptException in performDownloads() loop."); +// e.printStackTrace(); +// thatClosure.handleIoError(); +// } + catch (OutOfMemoryError e) + { + finished = true; // give up! + downloadable.handleIoError(e); + OutOfMemoryErrorHandler.handleException(e); + } + catch (Throwable e) + { + String interruptedStr = Thread.interrupted() ? " interrupted" : ""; + debugA("performDownloads() -- recovering from " + interruptedStr + " exception on " + + thatClosure + ":"); + e.printStackTrace(); + downloadable.handleIoError(e); + } + finally + { + synchronized (nonePendingLock) + { + pending--; + notifyAll(nonePendingLock); + } + + Site site = downloadable.getDownloadSite(); + if (site != null) + site.endDownload(downloadable.getDownloadLocation()); + + thatClosure.callContinuation(); // always call the continuation, error or not! + thatClosure.recycle(false); + } + } + } + + int sleepTime = dontWait || isLocalFile ? NO_SLEEP + : (lowMemory ? LOW_MEMORY_SLEEP + : (hurry ? SHORT_SLEEP + : (REGULAR_SLEEP + MathTools.random(100)))); +// debug("\t\t-------\tSleeping for: " + sleepTime); + Generic.sleep(sleepTime); + + if (stopRequested && isIdle()) + break; + } // while (!finished) + debug("exiting -- " + Thread.currentThread()); + } + + @Override + public String toString() + { + return super.toString() + "[" + name + "]"; + } + + @Override + public void stop() + { + stop(false); + } + + /** + * Stop our threads. + */ + public void stop(boolean kill) + { + // debug("stop()"); + finished = true; + + notifyAll(toDownload); + + if (downloadThreads != null) + { + for (int i = 0; i < downloadThreads.length; i++) + { + Thread thatThread = downloadThreads[i]; + if (kill) + thatThread.stop(); + downloadThreads[i] = null; + } + downloadThreads = null; + } + } + + public int waitingToDownload() + { + return toDownload.size(); + } + + /** + * @return true if we're backed up with unresloved downloads. + */ + public boolean highNumberWaiting() + { + return toDownload.size() > highThreshold; + } + + public boolean midNumberWaiting() + { + return toDownload.size() > midThreshold; + } + + public int lowPriority() + { + return lowPriority; + } + + public int midPriority() + { + return midPriority; + } + + public int highPriority() + { + return highPriority; + } + + public int pending() + { + return pending; + } + + public final Object nonePendingLock = new Object(); + + public void waitUntilNonePending() + { + synchronized (nonePendingLock) + { + while (pending > 0) + { + wait(nonePendingLock); + } + } + } + + /** + * Set whether or not this download monitor needs to wait after each download attempt + * @param noWait + */ + public void setNoWait(boolean noWait) + { + dontWait = noWait; + } + + public void setHurry(boolean hurry) + { + this.hurry = hurry; + debug("setHurry(" + hurry); + } + + public static NewPorterStemmer getStemmer() + { + Thread currentThread = Thread.currentThread(); + NewPorterStemmer stemmer = stemmersHash.get(currentThread); + if (stemmer == null) + { + stemmer = new NewPorterStemmer(); + stemmersHash.put(currentThread, stemmer); + } + return stemmer; + } + + /** + * check the number of elements in the toDownload Queue + * + * @return + */ + public int toDownloadSize() + { + return toDownload.size(); + } + + /** + * Stop performing downloads, and then Get rid of queued DownloadClosures. + */ + public void clear() + { + pause(); + toDownload.clear(); + } + + public void waitIfTooManyPending() + { + if (!highNumberWaiting()) + return; + synchronized (TOO_MANY_PENDING_LOCK) + { + try + { + debug("wait() on TOO_MANY_PENDING_LOCK"); + printQueue(); + TOO_MANY_PENDING_LOCK.wait(); + debug("finished wait() on TOO_MANY_PENDING_LOCK"); + } + catch (InterruptedException e) + { + Debug.weird(this, "Interrupted while waiting for TOO_MANY_PENDING_LOCK"); + e.printStackTrace(); + } + } + } + + public void printQueue() + { + synchronized (toDownload) + { + System.out.println(this.toString() + "QUEUE:"); + for (DownloadState d : toDownload) + { + System.out.println("\t" + d.downloadable); + } + } + System.out.println("\n"); + } + + public StatusReporter getStatus() + { + return status; + } + + public void setStatus(StatusReporter status) + { + this.status = status; + } + + /** + * Removes all downloadClosures that come from this site. + * @param site + */ + public void removeAllDownloadClosuresFromSite(Site site) + { + synchronized(toDownload) + { + ArrayList indexesToRemove = new ArrayList(); + int index = 0; + for(DownloadState d : toDownload) + if(d.downloadable != null && d.downloadable.getDownloadSite() == site) + indexesToRemove.add(index++); + if(indexesToRemove.size() > 0) + { + debug("Removing " + indexesToRemove.size() + " from the queue"); + for(int removeIndex : indexesToRemove) + toDownload.remove(removeIndex); + } + else + debug("Nothing to remove for site: " + site); + } + } + + /** + * @return the paused + */ + public boolean isPaused() + { + return paused; + } + + public int size() + { + return toDownloadSize(); + } + + /** + * check if the monitor is in idle state -- no downloads in the queue nor pending for dispatching. + * + * @return + */ + public boolean isIdle() + { + return pending() == 0 && toDownloadSize() == 0; + } + + /** + * this will cause the main loop (performDownloads()) stops after isIdle() == true. (after sleeping for some time) + * + */ + @Override + public void requestStop() + { + stopRequested = true; + } + + /** + * Reclaim memory if available memory is low. + * + * This should not be required in most cases. + * Subclasses can use this method to actively reclaim memory, if needed. + * + * @return true if memory is low and reclaimed. otherwise false. + */ + protected boolean reclaimMemoryIfLow() + { + // return Memory.reclaimIfLow(); + return false; + } + +} diff --git a/simplCore/src/ecologylab/concurrent/DownloadMonitorResult.java b/simplCore/src/ecologylab/concurrent/DownloadMonitorResult.java new file mode 100644 index 00000000..2ab81e14 --- /dev/null +++ b/simplCore/src/ecologylab/concurrent/DownloadMonitorResult.java @@ -0,0 +1,95 @@ +package ecologylab.concurrent; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import ecologylab.generic.Continuation; + +/** + * A utility that allows returning a Future object from a DownloadMonitor, which can be handy in + * some use cases. + * + * @author quyin + */ +public class DownloadMonitorResult implements Future, Continuation +{ + + private DownloadMonitor downloadMonitor; + + private T downloadable; + + private boolean done; + + private boolean cancelled; + + public DownloadMonitorResult(DownloadMonitor downloadMonitor, T downloadable) + { + this.downloadMonitor = downloadMonitor; + this.downloadable = downloadable; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) + { + if (!done && !cancelled) + { + downloadMonitor.cancelDownload(downloadable); + cancelled = true; + return true; + } + return false; + } + + @Override + public boolean isCancelled() + { + return cancelled; + } + + @Override + public boolean isDone() + { + return done; + } + + @Override + public T get() throws InterruptedException, ExecutionException + { + try + { + return get(10, TimeUnit.MINUTES); + } + catch (TimeoutException e) + { + return null; + } + } + + @Override + public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, + TimeoutException + { + synchronized (this) + { + if (!done) + { + this.wait(unit.toMillis(timeout)); + } + return downloadable; + } + } + + @Override + public void callback(T o) + { + synchronized (this) + { + done = true; + downloadable = o; + this.notifyAll(); + } + } + +} diff --git a/simplCore/src/ecologylab/concurrent/DownloadState.java b/simplCore/src/ecologylab/concurrent/DownloadState.java index b19f31b6..2d21cf7a 100644 --- a/simplCore/src/ecologylab/concurrent/DownloadState.java +++ b/simplCore/src/ecologylab/concurrent/DownloadState.java @@ -1,103 +1,103 @@ -package ecologylab.concurrent; - -import java.io.IOException; - -import ecologylab.generic.Continuation; -import ecologylab.generic.Debug; - -/** - * Closure that keeps state about a download, as it progresses. - */ -public class DownloadState -extends Debug -{ - T downloadable; - - private Continuation continuation; - private DownloadMonitor downloadMonitor; - private Thread downloadingThread; - - private boolean continued; - - private boolean recycled; - - DownloadState(T downloadable, Continuation dispatchTarget,DownloadMonitor downloadMonitor) - { - this.downloadable = downloadable; - this.continuation = dispatchTarget; - this.downloadMonitor = downloadMonitor; - } - - boolean shouldCancel() - { - boolean result = downloadable.isRecycled(); - if (!result) - { - BasicSite site = downloadable.getDownloadSite(); - if (site != null) - result = site.isDown(); - } - return result; - } - - /** - * Do the work to download this. - * @throws IOException - * - * @throws Exception - */ - void performDownload() throws IOException - { - downloadingThread = Thread.currentThread(); - //TODO need a lock here to prevent recycle() while downloading!!!!!! - if (downloadable != null && !downloadable.isRecycled()) - { - //Update site statistics if available - BasicSite site = downloadable.getDownloadSite(); - if(site != null) - site.beginActualDownload(); - downloadable.performDownload(); - if(site != null) - site.countNormalDownload(); - //ajit-added below condition for documents in local repository - //download monitor can't do it after return from here - if(site != null && downloadable.getDownloadLocation().isFile()) - site.endDownload(); - } - } - protected synchronized void callContinuation() - { - if (!continued && !recycled) - { - // debug("dispatch()"+" "+downloadable+" -> "+dispatchTarget); - continued = true; - downloadMonitor.dispatched++; - if (continuation != null) - continuation.callback(downloadable); - } - } - - @Override - public String toString() - { - String downloadableString = downloadable == null ? "recycled" : downloadable.toString(); - return super.toString() + "["+downloadableString +" "+ - downloadingThread + "]"; - } - - public void recycle(boolean recycleDownloadable) - { - if (!recycled) - { - recycled = true; - - if (recycleDownloadable) - downloadable.recycle(); - downloadable = null; - continuation = null; - downloadMonitor = null; - downloadingThread = null; - } - } - -} +package ecologylab.concurrent; + +import java.io.IOException; + +import ecologylab.generic.Continuation; +import ecologylab.generic.Debug; + +/** + * Closure that keeps state about a download, as it progresses. + */ +public class DownloadState +extends Debug +{ + T downloadable; + + private Continuation continuation; + private DownloadMonitor downloadMonitor; + private Thread downloadingThread; + + private boolean continued; + + private boolean recycled; + + DownloadState(T downloadable, Continuation dispatchTarget,DownloadMonitor downloadMonitor) + { + this.downloadable = downloadable; + this.continuation = dispatchTarget; + this.downloadMonitor = downloadMonitor; + } + + boolean shouldCancel() + { + boolean result = downloadable.isRecycled(); + if (!result) + { + Site site = downloadable.getDownloadSite(); + if (site != null) + result = site.isDown(); + } + return result; + } + + /** + * Do the work to download this. + * @throws IOException + * + * @throws Exception + */ + void performDownload() throws IOException + { + downloadingThread = Thread.currentThread(); + //TODO need a lock here to prevent recycle() while downloading!!!!!! + if (downloadable != null && !downloadable.isRecycled()) + { + //Update site statistics if available + Site site = downloadable.getDownloadSite(); + if(site != null) + site.beginDownload(downloadable.getDownloadLocation()); + downloadable.performDownload(); + if(site != null) + site.countNormalDownload(downloadable.getDownloadLocation()); + //ajit-added below condition for documents in local repository + //download monitor can't do it after return from here + if(site != null && downloadable.getDownloadLocation().isFile()) + site.endDownload(downloadable.getDownloadLocation()); + } + } + protected synchronized void callContinuation() + { + if (!continued && !recycled) + { + // debug("dispatch()"+" "+downloadable+" -> "+dispatchTarget); + continued = true; + downloadMonitor.dispatched++; + if (continuation != null) + continuation.callback(downloadable); + } + } + + @Override + public String toString() + { + String downloadableString = downloadable == null ? "recycled" : downloadable.toString(); + return super.toString() + "["+downloadableString +" "+ + downloadingThread + "]"; + } + + public void recycle(boolean recycleDownloadable) + { + if (!recycled) + { + recycled = true; + + if (recycleDownloadable) + downloadable.recycle(); + downloadable = null; + continuation = null; + downloadMonitor = null; + downloadingThread = null; + } + } + +} diff --git a/simplCore/src/ecologylab/concurrent/Downloadable.java b/simplCore/src/ecologylab/concurrent/Downloadable.java index f22f34c9..4f7847e3 100644 --- a/simplCore/src/ecologylab/concurrent/Downloadable.java +++ b/simplCore/src/ecologylab/concurrent/Downloadable.java @@ -1,65 +1,65 @@ -package ecologylab.concurrent; - -import java.io.IOException; - -import ecologylab.io.DownloadProcessor; -import ecologylab.net.ParsedURL; - -/** - * Objects that implement this interface can be passed to a {@link DownloadProcessor DownloadProcessor}. - * - * @author andruid - */ -public interface Downloadable -{ - - /** - * Called to start download. - */ - public void performDownload() - throws IOException; - - /** - * Called in case an IO error happens. - * @param e TODO - */ - public void handleIoError(Throwable e); - - /** - * True if the Downloadable has been recycled, and thus should not be downloaded. - * - * @return - */ - public boolean isRecycled(); - - public void recycle(); - - public BasicSite getSite(); - public BasicSite getDownloadSite(); - public ParsedURL location(); - public ParsedURL getDownloadLocation(); - - /** - * Can be used to reduce image download waits, in conjunction with BasicSite; - * otherwise ignored. - * - * @return - */ - public boolean isImage(); - - /** - * - * @return What to tell the user about what is being downloaded. - */ - public String message(); - - /** - * @return If this downloadable is cached somewhere (e.g. in memory or in cache servers), so - * that we don't need to hit the original website. - */ - public boolean isCached(); - - public DownloadableLogRecord getLogRecord(); - - //public void setDownloadableLogRecord(DownloadableLogRecord dlr); -} +package ecologylab.concurrent; + +import java.io.IOException; + +import ecologylab.io.DownloadProcessor; +import ecologylab.net.ParsedURL; + +/** + * Objects that implement this interface can be passed to a {@link DownloadProcessor DownloadProcessor}. + * + * @author andruid + */ +public interface Downloadable +{ + + /** + * Called to start download. + */ + public void performDownload() + throws IOException; + + /** + * Called in case an IO error happens. + * @param e TODO + */ + public void handleIoError(Throwable e); + + /** + * True if the Downloadable has been recycled, and thus should not be downloaded. + * + * @return + */ + public boolean isRecycled(); + + public void recycle(); + + public Site getSite(); + public Site getDownloadSite(); + public ParsedURL location(); + public ParsedURL getDownloadLocation(); + + /** + * Can be used to reduce image download waits, in conjunction with BasicSite; + * otherwise ignored. + * + * @return + */ + public boolean isImage(); + + /** + * + * @return What to tell the user about what is being downloaded. + */ + public String message(); + + /** + * @return If this downloadable is cached somewhere (e.g. in memory or in cache servers), so + * that we don't need to hit the original website. + */ + public boolean isCached(); + + public DownloadableLogRecord getLogRecord(); + + //public void setDownloadableLogRecord(DownloadableLogRecord dlr); +} diff --git a/simplCore/src/ecologylab/concurrent/DownloadableLogRecord.java b/simplCore/src/ecologylab/concurrent/DownloadableLogRecord.java index 1ea1aea8..00504af1 100644 --- a/simplCore/src/ecologylab/concurrent/DownloadableLogRecord.java +++ b/simplCore/src/ecologylab/concurrent/DownloadableLogRecord.java @@ -1,65 +1,67 @@ -package ecologylab.concurrent; - -import java.util.ArrayList; - -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_scalar; - -public class DownloadableLogRecord -{ - @simpl_collection("peek_interval") - ArrayList queuePeekIntervals = new ArrayList(); - - private long enQueueTimestamp; - - @simpl_scalar - boolean htmlCacheHit; - - @simpl_scalar - String urlHash; - - public void addQueuePeekInterval(long queuePeekInterval) - { - this.queuePeekIntervals.add(queuePeekInterval); - } - - public ArrayList getQueuePeekIntervals() - { - return queuePeekIntervals; - } - - public void setQueuePeekIntervals(ArrayList queuePeekIntervals) - { - this.queuePeekIntervals = queuePeekIntervals; - } - - public long getEnQueueTimestamp() - { - return enQueueTimestamp; - } - - public void setEnQueueTimestamp(long enQueueTimestamp) - { - this.enQueueTimestamp = enQueueTimestamp; - } - - public boolean isHtmlCacheHit() - { - return htmlCacheHit; - } - - public void setHtmlCacheHit(boolean bHTMLCacheHit) - { - this.htmlCacheHit = bHTMLCacheHit; - } - - public String getUrlHash() - { - return urlHash; - } - - public void setUrlHash(String urlHash) - { - this.urlHash = urlHash; - } -} +package ecologylab.concurrent; + +import ecologylab.logging.LogPost; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Logging information for a Downloadable. + * + * @author ajit + * @author quyin + */ +public class DownloadableLogRecord +{ + + @simpl_scalar + private String id; + + @simpl_composite + private LogPost logPost; + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public LogPost getLogPost() + { + return logPost; + } + + public LogPost logPost() + { + if (logPost == null) + { + synchronized (this) + { + if (logPost == null) + { + logPost = new LogPost(); + } + } + } + return logPost; + } + + public void addEnqueueEvent() + { + logPost().addEventNow(new EnqueueEvent()); + } + + public void addQueuePeekEvent() + { + logPost().addEventNow(new QueuePeekEvent()); + } + + public void addDownloadEvent() + { + logPost().addEventNow(new DownloadEvent()); + } + +} diff --git a/simplCore/src/ecologylab/concurrent/EnqueueEvent.java b/simplCore/src/ecologylab/concurrent/EnqueueEvent.java new file mode 100644 index 00000000..2040d876 --- /dev/null +++ b/simplCore/src/ecologylab/concurrent/EnqueueEvent.java @@ -0,0 +1,20 @@ +package ecologylab.concurrent; + +import ecologylab.logging.LogEvent; +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * When a downloadable is enqueued. + * + * @author quyin + */ +@simpl_inherit +public class EnqueueEvent extends LogEvent +{ + + public EnqueueEvent() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/concurrent/Monitor.java b/simplCore/src/ecologylab/concurrent/Monitor.java index bc502987..e6a4b65a 100644 --- a/simplCore/src/ecologylab/concurrent/Monitor.java +++ b/simplCore/src/ecologylab/concurrent/Monitor.java @@ -1,105 +1,105 @@ -package ecologylab.concurrent; - -import ecologylab.generic.ObservableDebug; - -/** - * Generic facilities for concurrent programming. - */ -public class Monitor extends ObservableDebug -{ - boolean done; - - /** - * Create a Monitor with a single done flag, that can be waited on. - * - */ - public Monitor() - { - - } - - /** - * If this is not yet done, then wait(); else return immediately. - */ - public synchronized void waitForDone() - { - if (!done) - wait(this); - } - - /** - * Mark this as done, as needed, and notify all waiting threads. - */ - public synchronized void done() - { - done = true; - notifyAll(this); - } - - /** - * Short-hand form: wait for the Object. Handles Interrupted exceptions. - * - * @param toLock - * @return true if the wait was completed without getting interrupted. - */ - public static boolean wait(Object toLock) - { - synchronized (toLock) - { - try - { - toLock.wait(); - return true; - // debug("dispatchDownloads() notified"); - } - catch (InterruptedException e) - { - // interrupt means stop - e.printStackTrace(); - return false; - } - } - } - - /** - * Short-hand form: wait for the Object. Handles Interrupted exceptions. - * - * @param toLock - * @param maxWaitTime - * @return true if the wait was completed without getting interrupted. - */ - public static boolean wait(Object toLock, int maxWaitTime) - { - synchronized (toLock) - { - try - { - toLock.wait(maxWaitTime); - return true; - // debug("dispatchDownloads() notified"); - } - catch (InterruptedException e) - { - // interrupt means stop - e.printStackTrace(); - return false; - } - } - } - - public static void notifyAll(Object lock) - { - synchronized (lock) - { - lock.notifyAll(); - } - } - - public static void notify(Object lock) - { - synchronized (lock) - { - lock.notify(); - } - } -} +package ecologylab.concurrent; + +import ecologylab.generic.ObservableDebug; + +/** + * Generic facilities for concurrent programming. + */ +public class Monitor extends ObservableDebug +{ + boolean done; + + /** + * Create a Monitor with a single done flag, that can be waited on. + * + */ + public Monitor() + { + + } + + /** + * If this is not yet done, then wait(); else return immediately. + */ + public synchronized void waitForDone() + { + if (!done) + wait(this); + } + + /** + * Mark this as done, as needed, and notify all waiting threads. + */ + public synchronized void done() + { + done = true; + notifyAll(this); + } + + /** + * Short-hand form: wait for the Object. Handles Interrupted exceptions. + * + * @param toLock + * @return true if the wait was completed without getting interrupted. + */ + public static boolean wait(Object toLock) + { + synchronized (toLock) + { + try + { + toLock.wait(); + return true; + // debug("dispatchDownloads() notified"); + } + catch (InterruptedException e) + { + // interrupt means stop + e.printStackTrace(); + return false; + } + } + } + + /** + * Short-hand form: wait for the Object. Handles Interrupted exceptions. + * + * @param toLock + * @param maxWaitTime + * @return true if the wait was completed without getting interrupted. + */ + public static boolean wait(Object toLock, int maxWaitTime) + { + synchronized (toLock) + { + try + { + toLock.wait(maxWaitTime); + return true; + // debug("dispatchDownloads() notified"); + } + catch (InterruptedException e) + { + // interrupt means stop + e.printStackTrace(); + return false; + } + } + } + + public static void notifyAll(Object lock) + { + synchronized (lock) + { + lock.notifyAll(); + } + } + + public static void notify(Object lock) + { + synchronized (lock) + { + lock.notify(); + } + } +} diff --git a/simplCore/src/ecologylab/concurrent/QueuePeekEvent.java b/simplCore/src/ecologylab/concurrent/QueuePeekEvent.java new file mode 100644 index 00000000..5bdbd498 --- /dev/null +++ b/simplCore/src/ecologylab/concurrent/QueuePeekEvent.java @@ -0,0 +1,20 @@ +package ecologylab.concurrent; + +import ecologylab.logging.LogEvent; +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * When a downloadable is peeked while it is at the head of the download queue. + * + * @author quyin + */ +@simpl_inherit +public class QueuePeekEvent extends LogEvent +{ + + public QueuePeekEvent() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/concurrent/RaiseMonitor.java b/simplCore/src/ecologylab/concurrent/RaiseMonitor.java index 04e29a8d..bc9233aa 100644 --- a/simplCore/src/ecologylab/concurrent/RaiseMonitor.java +++ b/simplCore/src/ecologylab/concurrent/RaiseMonitor.java @@ -1,162 +1,162 @@ -package ecologylab.concurrent; - -import ecologylab.appframework.TraceSlots; - - - -/** - * Extensions to thread provide the service of raising embellishments, - * and also functionality for starting & stopping this thang. - */ -public abstract class RaiseMonitor extends Thread { - - protected boolean running; - - /** - * A montior object used to control access to the wait() call that happens - * when a waitThenShow() request is received. - */ - protected final Object waitingLock = new Object(); - /** - * - */ - protected boolean waitingToDoRun; - private int raiseDelay; - - public RaiseMonitor(String name, int raiseDelay, boolean startNow) - { - super(name); - this.raiseDelay = raiseDelay; - if (startNow) - start(); - } - - @Override - public void start() - { - if (!running) - { - running = true; - super.start(); - } - } - - public synchronized void stopRunning() - { - if (running) - { - running = false; - synchronized (waitingLock) - { - notify(); - } - } - } - - /** - * Raise after a suitable delay, unless a cancel comes - * in first(). - */ - public synchronized void waitThenShow() - { - //println("RolloverFrame.delayThenShow()"); - notify(); - } - - @Override - public synchronized void run() - { - while (running) - { - try - { - //TraceSlots.rolloverRaiseStatus = 3000; - // wait for the next request - //Debug.println("RaiseMonitor.run() wait()"); - wait(); - - if (!running) - break; - - TraceSlots.rolloverRaiseStatus = 3001; - //Debug.println("RaiseMonitor.run() take waitingLock"); - synchronized (waitingLock) - { - waitingToDoRun = true; - // println("RolloverFrame.run() waitingLock.wait(RAISE_ABOUT_DELAY)"); - - TraceSlots.rolloverRaiseStatus = 3002; - // wait for a little delay before raising - waitingLock.wait(raiseDelay); - if (running == false) - break; - - //println("run() waitingToDoRun="+waitingToDoRun); - if (waitingToDoRun) - { - waitingToDoRun = false; - TraceSlots.rolloverRaiseStatus = 3003; - doRaise(); - TraceSlots.rolloverRaiseStatus = 3004; - } - else // waitingToDoRun changed asychronously by cancel() - { - TraceSlots.rolloverRaiseStatus = 3005; - //cancelRaise(); - //oneAndOnly.showEmbellishments = false; - } - } - //Debug.println("RaiseMonitor.run() released waitingLock"); - } catch (Exception e) - { - if (running) - e.printStackTrace(); - } - } - } - - protected abstract void doRaise(); - protected abstract void cancelRaise(); - - public void setRaiseDelay(int raiseDelay) - { - this.raiseDelay = raiseDelay; - } - /** - * If a request to raise the object is pending, cancel it. - */ - public boolean cancel() - { - synchronized (waitingLock) - { - boolean result = waitingToDoRun; - if (waitingToDoRun) - { - cancelRaise(); - - waitingToDoRun = false; - waitingLock.notify(); - } - return result; - } - } - - /** - * Checks if RaiseMonitor is currently waiting to execute doRaise() - * @return true if it is waiting. false if it is not. - */ - public boolean waitingToDoRun() - { - return waitingToDoRun; - } - - public Object waitingLock() - { - return waitingLock; - } - - public boolean isRunning() - { - return running; - } -} +package ecologylab.concurrent; + +import ecologylab.appframework.TraceSlots; + + + +/** + * Extensions to thread provide the service of raising embellishments, + * and also functionality for starting & stopping this thang. + */ +public abstract class RaiseMonitor extends Thread { + + protected boolean running; + + /** + * A montior object used to control access to the wait() call that happens + * when a waitThenShow() request is received. + */ + protected final Object waitingLock = new Object(); + /** + * + */ + protected boolean waitingToDoRun; + private int raiseDelay; + + public RaiseMonitor(String name, int raiseDelay, boolean startNow) + { + super(name); + this.raiseDelay = raiseDelay; + if (startNow) + start(); + } + + @Override + public void start() + { + if (!running) + { + running = true; + super.start(); + } + } + + public synchronized void stopRunning() + { + if (running) + { + running = false; + synchronized (waitingLock) + { + notify(); + } + } + } + + /** + * Raise after a suitable delay, unless a cancel comes + * in first(). + */ + public synchronized void waitThenShow() + { + //println("RolloverFrame.delayThenShow()"); + notify(); + } + + @Override + public synchronized void run() + { + while (running) + { + try + { + //TraceSlots.rolloverRaiseStatus = 3000; + // wait for the next request + //Debug.println("RaiseMonitor.run() wait()"); + wait(); + + if (!running) + break; + + TraceSlots.rolloverRaiseStatus = 3001; + //Debug.println("RaiseMonitor.run() take waitingLock"); + synchronized (waitingLock) + { + waitingToDoRun = true; + // println("RolloverFrame.run() waitingLock.wait(RAISE_ABOUT_DELAY)"); + + TraceSlots.rolloverRaiseStatus = 3002; + // wait for a little delay before raising + waitingLock.wait(raiseDelay); + if (running == false) + break; + + //println("run() waitingToDoRun="+waitingToDoRun); + if (waitingToDoRun) + { + waitingToDoRun = false; + TraceSlots.rolloverRaiseStatus = 3003; + doRaise(); + TraceSlots.rolloverRaiseStatus = 3004; + } + else // waitingToDoRun changed asychronously by cancel() + { + TraceSlots.rolloverRaiseStatus = 3005; + //cancelRaise(); + //oneAndOnly.showEmbellishments = false; + } + } + //Debug.println("RaiseMonitor.run() released waitingLock"); + } catch (Exception e) + { + if (running) + e.printStackTrace(); + } + } + } + + protected abstract void doRaise(); + protected abstract void cancelRaise(); + + public void setRaiseDelay(int raiseDelay) + { + this.raiseDelay = raiseDelay; + } + /** + * If a request to raise the object is pending, cancel it. + */ + public boolean cancel() + { + synchronized (waitingLock) + { + boolean result = waitingToDoRun; + if (waitingToDoRun) + { + cancelRaise(); + + waitingToDoRun = false; + waitingLock.notify(); + } + return result; + } + } + + /** + * Checks if RaiseMonitor is currently waiting to execute doRaise() + * @return true if it is waiting. false if it is not. + */ + public boolean waitingToDoRun() + { + return waitingToDoRun; + } + + public Object waitingLock() + { + return waitingLock; + } + + public boolean isRunning() + { + return running; + } +} diff --git a/simplCore/src/ecologylab/concurrent/Site.java b/simplCore/src/ecologylab/concurrent/Site.java new file mode 100644 index 00000000..2eb40ebd --- /dev/null +++ b/simplCore/src/ecologylab/concurrent/Site.java @@ -0,0 +1,122 @@ +package ecologylab.concurrent; + +import ecologylab.net.ParsedURL; + +/** + * An abstraction of a site for accessing and downloading. + * + * @author quyin + */ +public interface Site +{ + + /** + * @return The domain of this site. + */ + String domain(); + + /** + * @return If this site should be ignored for accessing and downloading information. + */ + boolean isIgnored(); + + /** + * Set if this site should be ignored. + */ + void setIgnored(boolean ignored); + + /** + * @return If the site is down. + */ + boolean isDown(); + + /** + * @return If we are downloading information from this site rignt how. + */ + boolean isDownloading(); + + /** + * @return The system time when last time we download information from this site. + */ + long getLastDownloadAt(); + + /** + * @return If downloading information from this site is constrained by an interval. + */ + boolean isDownloadingConstrained(); + + /** + * @return The specified, minimum interval between downloading from this site, in millisecond. + */ + long getDownloadInterval(); + + /** + * @return A decent interval between downloading from this site, in millisecond. + */ + long getDecentDownloadInterval(); + + /** + * @return The next system time that this site can be downloaded. + */ + long getNextAvailableTime(); + + /** + * Advance the internal record of the next system time that this site can be downloaded. + */ + void advanceNextAvailableTime(); + + /** + * Set a really long time before this site can be downloaded again. + */ + void setAbnormallyLongNextAvailableTime(); + + int getMaxDownloaders(); + + // **************************************************************** + // * Actions: * + // **************************************************************** + + /** + * Queue a location of this site for downloading. However, the downloading has not yet actually + * happened. + * + * @param location + */ + void queueDownload(ParsedURL location); + + /** + * Begin downloading information from this site with the given location. + * + * @param location + */ + void beginDownload(ParsedURL location); + + /** + * End downloading information from this site with the given location. There could be downloading + * ongoing for this site with other locations. + * + * @param location + */ + void endDownload(ParsedURL location); + + // **************************************************************** + // * Counters: * + // **************************************************************** + + void countNormalDownload(ParsedURL location); + + void countTimeout(ParsedURL location); + + void countFileNotFound(ParsedURL location); + + void countOtherIoError(ParsedURL location); + + int numOfNormalDownloads(); + + int numOfTimeouts(); + + int numOfNotFounds(); + + int numOfOtherIoError(); + +} \ No newline at end of file diff --git a/simplCore/src/ecologylab/concurrent/ThreadDebugger.java b/simplCore/src/ecologylab/concurrent/ThreadDebugger.java index b1b26b68..5ff685f9 100644 --- a/simplCore/src/ecologylab/concurrent/ThreadDebugger.java +++ b/simplCore/src/ecologylab/concurrent/ThreadDebugger.java @@ -1,281 +1,281 @@ -package ecologylab.concurrent; - -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Observer; - -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JPanel; - -import ecologylab.generic.Debug; -import ecologylab.generic.ObservableDebug; - -/** - * @author vikrams - * - * To change this generated comment edit the template variable "typecomment": - * Window>Preferences>Java>Templates. - * To enable and disable the creation of type comments go to - * Window>Preferences>Java>Code Generation. - */ -public class ThreadDebugger extends Debug -{ - static Hashtable threadEntriesByName = new Hashtable(); - static HashMap threadEntriesByThread = new HashMap(); - - static int nThreads; - - static JFrame threadControlFrame = new JFrame("Thread Debugger"); - static JPanel threadControlPanel = new JPanel(); - static Box verticalBox = new Box(BoxLayout.Y_AXIS); - static ActionListener threadToggler; - - static WindowObservable windowObservable = new WindowObservable(); - - static - { - nThreads = 0; - - threadToggler = new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - String action = e.getActionCommand(); - // ignore "start " / "pause " - we have the thread name as the key into the hashtable - - String threadName = action.substring(6,action.length()); - ThreadEntry ttd = (ThreadEntry)threadEntriesByName.get(threadName); - if (ttd == null) - { - // System.err.println("\nthreadName = " + threadName); - return; - } - - boolean paused = toggleAndReturnNewState(ttd); - - if (!paused) - { - resume(ttd); - } - } - }; - - threadControlPanel.add(verticalBox); - threadControlFrame.getContentPane().add(threadControlPanel); - threadControlFrame.pack(); - setPosition(); - - threadControlFrame.addWindowListener(windowObservable); - } - - public ThreadDebugger() - { - System.err.println("\nThreadDebugger constructor"); - } - - public static void registerMyself(Thread thread) - { - if (threadControlFrame == null) - return; - synchronized (threadEntriesByName) - { - final String threadName = thread.getName(); - if (threadEntriesByName.get(threadName) != null) - { - return; - } - ThreadEntry threadEntry = new ThreadEntry(thread); - threadEntriesByName.put(threadName, threadEntry); - threadEntriesByThread.put(thread, threadEntry); - nThreads++; - //println("ThreadDebugger.register("+thread+" COUNT = " +nThreads); - verticalBox.add(threadEntry.button); - threadControlFrame.pack(); - setPosition(); - } - } - - public static boolean toggleAndReturnNewState(ThreadEntry threadEntry) - { - threadEntry.button.setBackground(Color.yellow); - return threadEntry.toggleAndReturnNewState(); - } - - public static void waitIfPaused(Thread thread) - { -/* do nothing, because this may be the cause of race conditions, and no one has used it recently -- andruid 2/28/07 - ThreadEntry threadEntry = (ThreadEntry)threadEntriesByThread.get(thread); - if( threadEntry != null) - { - Object mylock = threadEntry.lock; - synchronized (mylock) - { - boolean paused = threadEntry.paused; - if (paused) - { - try - { - println("\nPAUSING THREAD " + thread.getName()); - threadEntry.button.setBackground(Color.red); - mylock.wait(); - }catch (InterruptedException e) - { - } - } - } - } - */ - } - - public static void resume(ThreadEntry threadEntry) - { - Object mylock = threadEntry.lock; - - synchronized (mylock) - { - println("\nRESTARTING THREAD " + threadEntry.thread.getName()); - mylock.notify(); - threadEntry.button.setBackground(Color.green); - } - } - - public static void removeMyself(Thread thread) - { - ThreadEntry removedTtd = (ThreadEntry)threadEntriesByThread.remove(thread.getName()); - threadEntriesByName.remove(thread); - verticalBox.remove(removedTtd.button); - threadControlFrame.pack(); - setPosition(); - } - - /** - * Clear all the thread collections -- eunyee - * - */ - public static void clear() - { - threadEntriesByName.clear(); - threadEntriesByThread.clear(); - nThreads = 0; - } - - static int xOriginal, yOriginal; - - public static void setPosition(int x, int y) - { - xOriginal = x; - yOriginal = y; - threadControlFrame.setLocation(x - currentWidth(),y - currentHeight()); - } - - static void setPosition() - { - threadControlFrame.setLocation(xOriginal - currentWidth(),yOriginal - currentHeight()); - } - - protected static int currentWidth() - { - return threadControlFrame.getWidth(); - } - - protected static int currentHeight() - { - return threadControlFrame.getHeight(); - } - public static void show() - { - println("ThreadDebugger.show()"); - threadControlFrame.setVisible(true); - } - public static void hide() - { - println("ThreadDebugger.hide()"); - threadControlFrame.setVisible(false); - } - - public static void addObserver(Observer o) - { - windowObservable.addObserver(o); - } - - static class WindowObservable extends ObservableDebug - implements WindowListener - { - @Override - public void windowClosing(WindowEvent e) - { - println("ThreadDebugger.windowClosing()"); - setChanged(); - notifyObservers("thread_debugger_close"); - } - @Override - public void windowOpened(WindowEvent e) - { - } - @Override - public void windowClosed(WindowEvent e) - { - } - @Override - public void windowIconified(WindowEvent e) - { - } - @Override - public void windowDeiconified(WindowEvent e) - { - } - @Override - public void windowActivated(WindowEvent e) - { - } - @Override - public void windowDeactivated(WindowEvent e) - { - } - } -} -/** - * An entry in the Hash of debuggable threads. - * - * @author andruid - */ - -class ThreadEntry -{ - Object lock = new Object(); - JButton button; - Thread thread; - boolean paused = false; - - ThreadEntry(Thread thread) - { - this.thread = thread; - button = new JButton("Pause " + thread.getName()); - button.addActionListener(ThreadDebugger.threadToggler); - } - - public boolean toggleAndReturnNewState() - { - paused = !paused; - - if (!paused) - { - button.setText("Pause " + thread.getName()); - } - else - { - button.setText("Start " + thread.getName()); - } - return paused; - } -} - +package ecologylab.concurrent; + +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Observer; + +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import ecologylab.generic.Debug; +import ecologylab.generic.ObservableDebug; + +/** + * @author vikrams + * + * To change this generated comment edit the template variable "typecomment": + * Window>Preferences>Java>Templates. + * To enable and disable the creation of type comments go to + * Window>Preferences>Java>Code Generation. + */ +public class ThreadDebugger extends Debug +{ + static Hashtable threadEntriesByName = new Hashtable(); + static HashMap threadEntriesByThread = new HashMap(); + + static int nThreads; + + static JFrame threadControlFrame = new JFrame("Thread Debugger"); + static JPanel threadControlPanel = new JPanel(); + static Box verticalBox = new Box(BoxLayout.Y_AXIS); + static ActionListener threadToggler; + + static WindowObservable windowObservable = new WindowObservable(); + + static + { + nThreads = 0; + + threadToggler = new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + String action = e.getActionCommand(); + // ignore "start " / "pause " - we have the thread name as the key into the hashtable + + String threadName = action.substring(6,action.length()); + ThreadEntry ttd = (ThreadEntry)threadEntriesByName.get(threadName); + if (ttd == null) + { + // System.err.println("\nthreadName = " + threadName); + return; + } + + boolean paused = toggleAndReturnNewState(ttd); + + if (!paused) + { + resume(ttd); + } + } + }; + + threadControlPanel.add(verticalBox); + threadControlFrame.getContentPane().add(threadControlPanel); + threadControlFrame.pack(); + setPosition(); + + threadControlFrame.addWindowListener(windowObservable); + } + + public ThreadDebugger() + { + System.err.println("\nThreadDebugger constructor"); + } + + public static void registerMyself(Thread thread) + { + if (threadControlFrame == null) + return; + synchronized (threadEntriesByName) + { + final String threadName = thread.getName(); + if (threadEntriesByName.get(threadName) != null) + { + return; + } + ThreadEntry threadEntry = new ThreadEntry(thread); + threadEntriesByName.put(threadName, threadEntry); + threadEntriesByThread.put(thread, threadEntry); + nThreads++; + //println("ThreadDebugger.register("+thread+" COUNT = " +nThreads); + verticalBox.add(threadEntry.button); + threadControlFrame.pack(); + setPosition(); + } + } + + public static boolean toggleAndReturnNewState(ThreadEntry threadEntry) + { + threadEntry.button.setBackground(Color.yellow); + return threadEntry.toggleAndReturnNewState(); + } + + public static void waitIfPaused(Thread thread) + { +/* do nothing, because this may be the cause of race conditions, and no one has used it recently -- andruid 2/28/07 + ThreadEntry threadEntry = (ThreadEntry)threadEntriesByThread.get(thread); + if( threadEntry != null) + { + Object mylock = threadEntry.lock; + synchronized (mylock) + { + boolean paused = threadEntry.paused; + if (paused) + { + try + { + println("\nPAUSING THREAD " + thread.getName()); + threadEntry.button.setBackground(Color.red); + mylock.wait(); + }catch (InterruptedException e) + { + } + } + } + } + */ + } + + public static void resume(ThreadEntry threadEntry) + { + Object mylock = threadEntry.lock; + + synchronized (mylock) + { + println("\nRESTARTING THREAD " + threadEntry.thread.getName()); + mylock.notify(); + threadEntry.button.setBackground(Color.green); + } + } + + public static void removeMyself(Thread thread) + { + ThreadEntry removedTtd = (ThreadEntry)threadEntriesByThread.remove(thread.getName()); + threadEntriesByName.remove(thread); + verticalBox.remove(removedTtd.button); + threadControlFrame.pack(); + setPosition(); + } + + /** + * Clear all the thread collections -- eunyee + * + */ + public static void clear() + { + threadEntriesByName.clear(); + threadEntriesByThread.clear(); + nThreads = 0; + } + + static int xOriginal, yOriginal; + + public static void setPosition(int x, int y) + { + xOriginal = x; + yOriginal = y; + threadControlFrame.setLocation(x - currentWidth(),y - currentHeight()); + } + + static void setPosition() + { + threadControlFrame.setLocation(xOriginal - currentWidth(),yOriginal - currentHeight()); + } + + protected static int currentWidth() + { + return threadControlFrame.getWidth(); + } + + protected static int currentHeight() + { + return threadControlFrame.getHeight(); + } + public static void show() + { + println("ThreadDebugger.show()"); + threadControlFrame.setVisible(true); + } + public static void hide() + { + println("ThreadDebugger.hide()"); + threadControlFrame.setVisible(false); + } + + public static void addObserver(Observer o) + { + windowObservable.addObserver(o); + } + + static class WindowObservable extends ObservableDebug + implements WindowListener + { + @Override + public void windowClosing(WindowEvent e) + { + println("ThreadDebugger.windowClosing()"); + setChanged(); + notifyObservers("thread_debugger_close"); + } + @Override + public void windowOpened(WindowEvent e) + { + } + @Override + public void windowClosed(WindowEvent e) + { + } + @Override + public void windowIconified(WindowEvent e) + { + } + @Override + public void windowDeiconified(WindowEvent e) + { + } + @Override + public void windowActivated(WindowEvent e) + { + } + @Override + public void windowDeactivated(WindowEvent e) + { + } + } +} +/** + * An entry in the Hash of debuggable threads. + * + * @author andruid + */ + +class ThreadEntry +{ + Object lock = new Object(); + JButton button; + Thread thread; + boolean paused = false; + + ThreadEntry(Thread thread) + { + this.thread = thread; + button = new JButton("Pause " + thread.getName()); + button.addActionListener(ThreadDebugger.threadToggler); + } + + public boolean toggleAndReturnNewState() + { + paused = !paused; + + if (!paused) + { + button.setText("Pause " + thread.getName()); + } + else + { + button.setText("Start " + thread.getName()); + } + return paused; + } +} + diff --git a/simplCore/src/ecologylab/concurrent/package.html b/simplCore/src/ecologylab/concurrent/package.html index e74c7270..c9f22de7 100644 --- a/simplCore/src/ecologylab/concurrent/package.html +++ b/simplCore/src/ecologylab/concurrent/package.html @@ -1,3 +1,3 @@ - -Modules for concurrent programming, such as Monitors. - + +Modules for concurrent programming, such as Monitors. + diff --git a/simplCore/src/ecologylab/generic/ArrayListDebug.java b/simplCore/src/ecologylab/generic/ArrayListDebug.java index fbb31b51..a17ffa18 100644 --- a/simplCore/src/ecologylab/generic/ArrayListDebug.java +++ b/simplCore/src/ecologylab/generic/ArrayListDebug.java @@ -1,87 +1,87 @@ -package ecologylab.generic; - -import java.util.ArrayList; - -/** - * An {@link java.util.ArrayList ArrayList}, extended with convenient - * connections to our {@link Debug Debug} methods. - */ -public class ArrayListDebug -extends ArrayList -{ - protected ArrayListDebug() - { - super(); -// AllocationDebugger.constructed(this); - } - protected ArrayListDebug(int initialCapacity) - { - super(initialCapacity); -// AllocationDebugger.constructed(this); - } - public final void debug(String message) - { - Debug.println(this, message); - } - public final void debugA(String message) - { - Debug.printlnA(this, message); - } - public final void debugI(String message) - { - Debug.printlnI(this, message); - } - - public final void debug(int messageLevel, String message) - { - Debug.println(this, messageLevel, message); - } - - public final void debugA(int level, String message) - { - Debug.printlnA(this, level, message); - } - public final void debugI(int level, String message) - { - Debug.printlnI(this, level, message); - } - - public final String getClassName() - { - return Debug.getClassSimpleName(this); - } - public static void print(String message) - { - Debug.print(message); - } - public static void println(String message) - { - Debug.println(message); - } - public static void println(StringBuffer buffy) - { - Debug.println(buffy); - } - @Override -public String toString() - { - return Debug.toString(this); - } - public static void println(String className, - int messageLevel, String message) - { - Debug.println(className, messageLevel, message); - } - public final boolean show(int messageLevel) - { - return Debug.show(this, messageLevel); - } - public String superString() - { - return super.toString(); - } -// protected final void finalize() -// { -// AllocationDebugger.finalized(this); -// } -} +package ecologylab.generic; + +import java.util.ArrayList; + +/** + * An {@link java.util.ArrayList ArrayList}, extended with convenient + * connections to our {@link Debug Debug} methods. + */ +public class ArrayListDebug +extends ArrayList +{ + protected ArrayListDebug() + { + super(); +// AllocationDebugger.constructed(this); + } + protected ArrayListDebug(int initialCapacity) + { + super(initialCapacity); +// AllocationDebugger.constructed(this); + } + public final void debug(String message) + { + Debug.println(this, message); + } + public final void debugA(String message) + { + Debug.printlnA(this, message); + } + public final void debugI(String message) + { + Debug.printlnI(this, message); + } + + public final void debug(int messageLevel, String message) + { + Debug.println(this, messageLevel, message); + } + + public final void debugA(int level, String message) + { + Debug.printlnA(this, level, message); + } + public final void debugI(int level, String message) + { + Debug.printlnI(this, level, message); + } + + public final String getClassName() + { + return Debug.getClassSimpleName(this); + } + public static void print(String message) + { + Debug.print(message); + } + public static void println(String message) + { + Debug.println(message); + } + public static void println(StringBuffer buffy) + { + Debug.println(buffy); + } + @Override +public String toString() + { + return Debug.toString(this); + } + public static void println(String className, + int messageLevel, String message) + { + Debug.println(className, messageLevel, message); + } + public final boolean show(int messageLevel) + { + return Debug.show(this, messageLevel); + } + public String superString() + { + return super.toString(); + } +// protected final void finalize() +// { +// AllocationDebugger.finalized(this); +// } +} diff --git a/simplCore/src/ecologylab/generic/AutoCleanerMap.java b/simplCore/src/ecologylab/generic/AutoCleanerMap.java index 6246eb98..db1df675 100644 --- a/simplCore/src/ecologylab/generic/AutoCleanerMap.java +++ b/simplCore/src/ecologylab/generic/AutoCleanerMap.java @@ -1,219 +1,219 @@ -/** - * - */ -package ecologylab.generic; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.concurrent.ConcurrentHashMap; - -/** - * This class runs in order to clean out unrefreshed elements of a Map on a specified interval. - * Access to the Map should go through this object to ensure proper sychonous access. - * - * Note that this object will automatically remove elements that have been in the map, and unused, - * for too long (per the liveTime argument) and will persist for at LEAST as long as the liveTime - * argument. - * - * I'm sure there's a nice mathmematical way to explain it, but each item lasts until the next - * cleanupInterval...if, at the interval, it has been idle for more than liveTime, it is removed and - * Java GC will take care of it when it gets around to it. - * - * This object automatically starts up a monitoring thread whenever it contains items, and shuts - * itself off when there are no items. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class AutoCleanerMap extends ConcurrentHashMap implements Runnable -{ - private static final long serialVersionUID = 1L; - - HashMap timeTrackerMap = new HashMap(); - - private long liveTime; - - private long cleanupInterval; - - private boolean running = false; - - private Thread t; - - public AutoCleanerMap(long liveTime, long cleanupInterval) - { - this.liveTime = liveTime; - this.cleanupInterval = cleanupInterval; - } - - /** - * Finds the matching value, calls access for it, then returns it. - * - * @see java.util.concurrent.ConcurrentHashMap#get(java.lang.Object) - */ - @SuppressWarnings("unchecked") - @Override - public synchronized VALUE get(Object key) - { - try - { - KEY actualKey = (KEY) key; - this.access(actualKey); - return super.get(actualKey); - } - catch (ClassCastException e) - { - e.printStackTrace(); - Debug - .println("This stupid method takes Objects instead of things bound by the appropriate parameterization of this class. Somehow, you've managed to pass it an Object that does not cast correctly. Well done...you broke it."); - return null; - } - } - - private synchronized void start() - { - this.running = true; - - t = new Thread(this); - t.start(); - } - - private synchronized void stop() - { - this.running = false; - t.interrupt(); - } - - @Override - public synchronized VALUE put(KEY key, VALUE value) - { - TimeTracker tt = new TimeTracker(key); - // we're just letting the old time tracker get thrown away - timeTrackerMap.put(key, tt); - - if (this.size() == 0) - { - this.start(); - } - - return super.put(key, value); - } - - @SuppressWarnings("unchecked") - @Override - public synchronized VALUE remove(Object key) - { - try - { - KEY actualKey = (KEY) key; - this.timeTrackerMap.remove(actualKey); - - if (this.size() == 1) - { - this.stop(); - } - - return super.remove(actualKey); - } - catch (ClassCastException e) - { - e.printStackTrace(); - Debug - .println("This stupid method takes Objects instead of things bound by the appropriate parameterization of this class. Somehow, you've managed to pass it an Object that does not cast correctly. Well done...you broke it."); - return null; - } - } - - public synchronized void access(KEY key) - { - // look up the TimeTracker object - TimeTracker tt = timeTrackerMap.get(key); - - if (tt != null) - { - tt.access(); - } - } - - private synchronized void cleanup() - { - long cleanupTime = System.currentTimeMillis(); - - ArrayList toRemove = new ArrayList(); - - Iterator trackerIter = timeTrackerMap.keySet().iterator(); - while (trackerIter.hasNext()) - - { - KEY k = trackerIter.next(); - - TimeTracker tt = timeTrackerMap.get(k); - - if (cleanupTime - tt.getLastAccess() > liveTime) - { // too old - toRemove.add(tt.key); - } - } - - for (KEY k : toRemove) - { - this.remove(k); - timeTrackerMap.remove(k); - - Debug.println("**********************************cleanup removed: " + k); - } - } - - @Override - public void run() - { - Debug.println("Starting up AutoMapCleaner."); - while (running) - { - try - { - Thread.sleep(cleanupInterval); - } - catch (InterruptedException e) - { - Thread.interrupted(); - e.printStackTrace(); - } - - Debug.println("cleaning..."); - this.cleanup(); - Debug.println("done."); - } - Debug.println("Stopping AutoMapCleaner."); - } - - /** - * TimeTracker matches an object of type KEY to a Date. It is meant to track a Key into a Hash. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ - class TimeTracker - { - private long lastAccess; - - private KEY key; - - public TimeTracker(KEY key) - { - this.key = key; - lastAccess = System.currentTimeMillis(); - } - - public void access() - { - lastAccess = System.currentTimeMillis(); - } - - /** - * @return the lastAccess - */ - public long getLastAccess() - { - return lastAccess; - } - } -} +/** + * + */ +package ecologylab.generic; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; + +/** + * This class runs in order to clean out unrefreshed elements of a Map on a specified interval. + * Access to the Map should go through this object to ensure proper sychonous access. + * + * Note that this object will automatically remove elements that have been in the map, and unused, + * for too long (per the liveTime argument) and will persist for at LEAST as long as the liveTime + * argument. + * + * I'm sure there's a nice mathmematical way to explain it, but each item lasts until the next + * cleanupInterval...if, at the interval, it has been idle for more than liveTime, it is removed and + * Java GC will take care of it when it gets around to it. + * + * This object automatically starts up a monitoring thread whenever it contains items, and shuts + * itself off when there are no items. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class AutoCleanerMap extends ConcurrentHashMap implements Runnable +{ + private static final long serialVersionUID = 1L; + + HashMap timeTrackerMap = new HashMap(); + + private long liveTime; + + private long cleanupInterval; + + private boolean running = false; + + private Thread t; + + public AutoCleanerMap(long liveTime, long cleanupInterval) + { + this.liveTime = liveTime; + this.cleanupInterval = cleanupInterval; + } + + /** + * Finds the matching value, calls access for it, then returns it. + * + * @see java.util.concurrent.ConcurrentHashMap#get(java.lang.Object) + */ + @SuppressWarnings("unchecked") + @Override + public synchronized VALUE get(Object key) + { + try + { + KEY actualKey = (KEY) key; + this.access(actualKey); + return super.get(actualKey); + } + catch (ClassCastException e) + { + e.printStackTrace(); + Debug + .println("This stupid method takes Objects instead of things bound by the appropriate parameterization of this class. Somehow, you've managed to pass it an Object that does not cast correctly. Well done...you broke it."); + return null; + } + } + + private synchronized void start() + { + this.running = true; + + t = new Thread(this); + t.start(); + } + + private synchronized void stop() + { + this.running = false; + t.interrupt(); + } + + @Override + public synchronized VALUE put(KEY key, VALUE value) + { + TimeTracker tt = new TimeTracker(key); + // we're just letting the old time tracker get thrown away + timeTrackerMap.put(key, tt); + + if (this.size() == 0) + { + this.start(); + } + + return super.put(key, value); + } + + @SuppressWarnings("unchecked") + @Override + public synchronized VALUE remove(Object key) + { + try + { + KEY actualKey = (KEY) key; + this.timeTrackerMap.remove(actualKey); + + if (this.size() == 1) + { + this.stop(); + } + + return super.remove(actualKey); + } + catch (ClassCastException e) + { + e.printStackTrace(); + Debug + .println("This stupid method takes Objects instead of things bound by the appropriate parameterization of this class. Somehow, you've managed to pass it an Object that does not cast correctly. Well done...you broke it."); + return null; + } + } + + public synchronized void access(KEY key) + { + // look up the TimeTracker object + TimeTracker tt = timeTrackerMap.get(key); + + if (tt != null) + { + tt.access(); + } + } + + private synchronized void cleanup() + { + long cleanupTime = System.currentTimeMillis(); + + ArrayList toRemove = new ArrayList(); + + Iterator trackerIter = timeTrackerMap.keySet().iterator(); + while (trackerIter.hasNext()) + + { + KEY k = trackerIter.next(); + + TimeTracker tt = timeTrackerMap.get(k); + + if (cleanupTime - tt.getLastAccess() > liveTime) + { // too old + toRemove.add(tt.key); + } + } + + for (KEY k : toRemove) + { + this.remove(k); + timeTrackerMap.remove(k); + + Debug.println("**********************************cleanup removed: " + k); + } + } + + @Override + public void run() + { + Debug.println("Starting up AutoMapCleaner."); + while (running) + { + try + { + Thread.sleep(cleanupInterval); + } + catch (InterruptedException e) + { + Thread.interrupted(); + e.printStackTrace(); + } + + Debug.println("cleaning..."); + this.cleanup(); + Debug.println("done."); + } + Debug.println("Stopping AutoMapCleaner."); + } + + /** + * TimeTracker matches an object of type KEY to a Date. It is meant to track a Key into a Hash. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ + class TimeTracker + { + private long lastAccess; + + private KEY key; + + public TimeTracker(KEY key) + { + this.key = key; + lastAccess = System.currentTimeMillis(); + } + + public void access() + { + lastAccess = System.currentTimeMillis(); + } + + /** + * @return the lastAccess + */ + public long getLastAccess() + { + return lastAccess; + } + } +} diff --git a/simplCore/src/ecologylab/generic/BooleanSlot.java b/simplCore/src/ecologylab/generic/BooleanSlot.java index c942687a..b75d3fc0 100644 --- a/simplCore/src/ecologylab/generic/BooleanSlot.java +++ b/simplCore/src/ecologylab/generic/BooleanSlot.java @@ -1,16 +1,16 @@ -package ecologylab.generic; - - -/** - * Reference version of a boolean type. Re-writable, unlike java.lang.Boolean. - */ -public class BooleanSlot -extends Object -{ - public boolean value; - public BooleanSlot(boolean b) - { - super(); - value = b; - } -} +package ecologylab.generic; + + +/** + * Reference version of a boolean type. Re-writable, unlike java.lang.Boolean. + */ +public class BooleanSlot +extends Object +{ + public boolean value; + public BooleanSlot(boolean b) + { + super(); + value = b; + } +} diff --git a/simplCore/src/ecologylab/generic/Bounds.java b/simplCore/src/ecologylab/generic/Bounds.java index 971fdf6d..89f0739f 100644 --- a/simplCore/src/ecologylab/generic/Bounds.java +++ b/simplCore/src/ecologylab/generic/Bounds.java @@ -1,54 +1,54 @@ -/* - * Copyright 1996-2002 by Andruid Kerne. All rights reserved. - * CONFIDENTIAL. Use is subject to license terms. - */ -package ecologylab.generic; - -import java.awt.Rectangle; - -/** - * Representation of a bounding box, based on 2 points. - */ -public class Bounds -{ - public int xMin, yMin, xMax, yMax; - - public Bounds(int xMinArg, int yMinArg, int xMaxArg, int yMaxArg) - { - xMin = xMinArg; - yMin = yMinArg; - xMax = xMaxArg; - yMax = yMaxArg; - } - public Bounds(Bounds oldBounds) - { - xMin = oldBounds.xMin; - yMin = oldBounds.yMin; - xMax = oldBounds.xMax; - yMax = oldBounds.yMax; - } - public Bounds() - { - // TODO Auto-generated constructor stub - } - @Override - public boolean equals(Object other) - { - Bounds fb = (Bounds)other; - - return ((fb != null) && (fb.xMin == this.xMin) && (fb.xMax == this.xMax) - && (fb.yMin == this.yMin) && (fb.yMax == this.yMax)); - } - @Override - public String toString() - { - return "Bounds[" + xMin+","+yMin+"; "+xMax+","+yMax +"]"; - } - - public boolean intersects(Rectangle intersectingRect) - { - Rectangle boundsRect = new Rectangle(xMin, yMin, xMax - xMin, yMax - yMin); - - return boundsRect.intersects(intersectingRect); - } -} +/* + * Copyright 1996-2002 by Andruid Kerne. All rights reserved. + * CONFIDENTIAL. Use is subject to license terms. + */ +package ecologylab.generic; + +import java.awt.Rectangle; + +/** + * Representation of a bounding box, based on 2 points. + */ +public class Bounds +{ + public int xMin, yMin, xMax, yMax; + + public Bounds(int xMinArg, int yMinArg, int xMaxArg, int yMaxArg) + { + xMin = xMinArg; + yMin = yMinArg; + xMax = xMaxArg; + yMax = yMaxArg; + } + public Bounds(Bounds oldBounds) + { + xMin = oldBounds.xMin; + yMin = oldBounds.yMin; + xMax = oldBounds.xMax; + yMax = oldBounds.yMax; + } + public Bounds() + { + // TODO Auto-generated constructor stub + } + @Override + public boolean equals(Object other) + { + Bounds fb = (Bounds)other; + + return ((fb != null) && (fb.xMin == this.xMin) && (fb.xMax == this.xMax) + && (fb.yMin == this.yMin) && (fb.yMax == this.yMax)); + } + @Override + public String toString() + { + return "Bounds[" + xMin+","+yMin+"; "+xMax+","+yMax +"]"; + } + + public boolean intersects(Rectangle intersectingRect) + { + Rectangle boundsRect = new Rectangle(xMin, yMin, xMax - xMin, yMax - yMin); + + return boundsRect.intersects(intersectingRect); + } +} diff --git a/simplCore/src/ecologylab/generic/ByteArrayOutputStreamPool.java b/simplCore/src/ecologylab/generic/ByteArrayOutputStreamPool.java index f8930f54..25d38384 100644 --- a/simplCore/src/ecologylab/generic/ByteArrayOutputStreamPool.java +++ b/simplCore/src/ecologylab/generic/ByteArrayOutputStreamPool.java @@ -1,39 +1,39 @@ -package ecologylab.generic; - -import java.io.ByteArrayOutputStream; - -/** - * - * @author quyin - * - */ -public class ByteArrayOutputStreamPool extends ResourcePool -{ - - public static int DEFAULT_BYTE_ARRAY_SIZE = 1024 * 16; // default size: 16k - - protected ByteArrayOutputStreamPool() - { - super(1, 1); - } - - @Override - protected ByteArrayOutputStream generateNewResource() - { - return new ByteArrayOutputStream(DEFAULT_BYTE_ARRAY_SIZE); - } - - @Override - protected void clean(ByteArrayOutputStream objectToClean) - { - objectToClean.reset(); - } - - private static ByteArrayOutputStreamPool singleton = new ByteArrayOutputStreamPool(); - - public static ByteArrayOutputStreamPool get() - { - return singleton; - } - -} +package ecologylab.generic; + +import java.io.ByteArrayOutputStream; + +/** + * + * @author quyin + * + */ +public class ByteArrayOutputStreamPool extends ResourcePool +{ + + public static int DEFAULT_BYTE_ARRAY_SIZE = 1024 * 16; // default size: 16k + + protected ByteArrayOutputStreamPool() + { + super(1, 1); + } + + @Override + protected ByteArrayOutputStream generateNewResource() + { + return new ByteArrayOutputStream(DEFAULT_BYTE_ARRAY_SIZE); + } + + @Override + protected void clean(ByteArrayOutputStream objectToClean) + { + objectToClean.reset(); + } + + private static ByteArrayOutputStreamPool singleton = new ByteArrayOutputStreamPool(); + + public static ByteArrayOutputStreamPool get() + { + return singleton; + } + +} diff --git a/simplCore/src/ecologylab/generic/CharBufferPool.java b/simplCore/src/ecologylab/generic/CharBufferPool.java index 170ad3f5..107b3149 100644 --- a/simplCore/src/ecologylab/generic/CharBufferPool.java +++ b/simplCore/src/ecologylab/generic/CharBufferPool.java @@ -1,48 +1,48 @@ -/** - * - */ -package ecologylab.generic; - -import java.nio.CharBuffer; - -/** - * ResourcePool for StringBuilders. - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class CharBufferPool extends ResourcePoolWithSize -{ - /** - * @param builderSize the size of StringBuilders created within this pool. - */ - public CharBufferPool(int builderSize) - { - this(DEFAULT_POOL_SIZE, DEFAULT_POOL_SIZE/4, builderSize); - } - - /** - * @param poolSize - */ - public CharBufferPool(int poolSize, int minimumCapacity, int builderSize) - { - super(poolSize, minimumCapacity, builderSize); - } - - /** - * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) - */ - @Override protected void clean(CharBuffer objectToClean) - { - objectToClean.clear(); - } - - /** - * @see ecologylab.generic.ResourcePool#generateNewResource() - */ - @Override protected CharBuffer generateNewResource() - { - return CharBuffer.allocate(this.resourceObjectCapacity); - } - -} +/** + * + */ +package ecologylab.generic; + +import java.nio.CharBuffer; + +/** + * ResourcePool for StringBuilders. + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class CharBufferPool extends ResourcePoolWithSize +{ + /** + * @param builderSize the size of StringBuilders created within this pool. + */ + public CharBufferPool(int builderSize) + { + this(DEFAULT_POOL_SIZE, DEFAULT_POOL_SIZE/4, builderSize); + } + + /** + * @param poolSize + */ + public CharBufferPool(int poolSize, int minimumCapacity, int builderSize) + { + super(poolSize, minimumCapacity, builderSize); + } + + /** + * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) + */ + @Override protected void clean(CharBuffer objectToClean) + { + objectToClean.clear(); + } + + /** + * @see ecologylab.generic.ResourcePool#generateNewResource() + */ + @Override protected CharBuffer generateNewResource() + { + return CharBuffer.allocate(this.resourceObjectCapacity); + } + +} diff --git a/simplCore/src/ecologylab/generic/ClassAndCollectionIterator.java b/simplCore/src/ecologylab/generic/ClassAndCollectionIterator.java index 058cdf0a..6887d508 100644 --- a/simplCore/src/ecologylab/generic/ClassAndCollectionIterator.java +++ b/simplCore/src/ecologylab/generic/ClassAndCollectionIterator.java @@ -1,113 +1,113 @@ -package ecologylab.generic; - -import java.lang.reflect.Field; -import java.util.Iterator; - -import ecologylab.serialization.FieldDescriptor; - -/** - * Iterates through a Collection of things, and then through an Iterator - * of such (nested) Collections of things. - * Provides flat access to all members. - * - * @author jmole, damaraju - * - * @param Class that we iterate over. - * @param Class of objects that are applied in the context of what we iterate over. - * This typically starts as this, but shifts as we iterate through - * the nested Collection of Iterators. - */ -public class ClassAndCollectionIterator> -implements Iterator -{ - private Iterator iterator; - private Iterator collectionIterator; - private O root; - private O currentObject; - - /** - * - * @param firstObject - The object whose elements need to be iterated over. - */ - public ClassAndCollectionIterator(O firstObject) - { - root = firstObject; - this.iterator = firstObject.iterator(); - } - - /** - * @return The next field in the Object.
- * If the next object is a non-null collection, it iterates through the objects of that collection - */ - @Override -public O next() - { - try - { - if (collectionIterator != null) - return nextInCollection(); - - if (iterator.hasNext()) - { - I firstNext = iterator.next(); - Field field = firstNext.getField(); - if(firstNext.isCollection()) - { - Iterable collection = (Iterable)field.get(root); - if(collection != null) - { - collectionIterator = collection.iterator(); - return nextInCollection(); - } - else - { - //Collection is null ? - //Debug.println("next(): Collection is null"); - return next(); - } - - } - O next = (O) field.get(root); - currentObject = next; - return next; - } - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return null; - } - - private O nextInCollection() - { - if (!collectionIterator.hasNext()) { - collectionIterator = null; - return next(); - } - O next = collectionIterator.next(); - currentObject = next; - return next; - } - - /** - * - * @return - */ - public O currentObject() - { - return currentObject; - } - - @Override -public void remove() - { - throw new UnsupportedOperationException(); - } - - @Override -public boolean hasNext() - { - return iterator.hasNext() || (collectionIterator != null && collectionIterator.hasNext()); - } -} +package ecologylab.generic; + +import java.lang.reflect.Field; +import java.util.Iterator; + +import ecologylab.serialization.FieldDescriptor; + +/** + * Iterates through a Collection of things, and then through an Iterator + * of such (nested) Collections of things. + * Provides flat access to all members. + * + * @author jmole, damaraju + * + * @param Class that we iterate over. + * @param Class of objects that are applied in the context of what we iterate over. + * This typically starts as this, but shifts as we iterate through + * the nested Collection of Iterators. + */ +public class ClassAndCollectionIterator> +implements Iterator +{ + private Iterator iterator; + private Iterator collectionIterator; + private O root; + private O currentObject; + + /** + * + * @param firstObject - The object whose elements need to be iterated over. + */ + public ClassAndCollectionIterator(O firstObject) + { + root = firstObject; + this.iterator = firstObject.iterator(); + } + + /** + * @return The next field in the Object.
+ * If the next object is a non-null collection, it iterates through the objects of that collection + */ + @Override +public O next() + { + try + { + if (collectionIterator != null) + return nextInCollection(); + + if (iterator.hasNext()) + { + I firstNext = iterator.next(); + Field field = firstNext.getField(); + if(firstNext.isCollection()) + { + Iterable collection = (Iterable)field.get(root); + if(collection != null) + { + collectionIterator = collection.iterator(); + return nextInCollection(); + } + else + { + //Collection is null ? + //Debug.println("next(): Collection is null"); + return next(); + } + + } + O next = (O) field.get(root); + currentObject = next; + return next; + } + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + + private O nextInCollection() + { + if (!collectionIterator.hasNext()) { + collectionIterator = null; + return next(); + } + O next = collectionIterator.next(); + currentObject = next; + return next; + } + + /** + * + * @return + */ + public O currentObject() + { + return currentObject; + } + + @Override +public void remove() + { + throw new UnsupportedOperationException(); + } + + @Override +public boolean hasNext() + { + return iterator.hasNext() || (collectionIterator != null && collectionIterator.hasNext()); + } +} diff --git a/simplCore/src/ecologylab/generic/Colors.java b/simplCore/src/ecologylab/generic/Colors.java index 9c27e2b6..b29fa375 100644 --- a/simplCore/src/ecologylab/generic/Colors.java +++ b/simplCore/src/ecologylab/generic/Colors.java @@ -1,45 +1,45 @@ -/* - * Copyright 1996-2002 by Andruid Kerne. All rights reserved. - * CONFIDENTIAL. Use is subject to license terms. - */ -package ecologylab.generic; - -/** - * Constants for RGB/Alpha and HSV color space operations. - */ -public interface Colors -{ - public static final int HUE = 0; - public static final int SAT = 1; - public static final int VAL = 2; - - public static final int ALPHA = 0xff000000; - public static final int RGB = 0xffffff; - public static final int R = 0xff0000; - public static final int G = 0xff00; - public static final int B = 0xff; - - public static final float YELLOW = 60.0f/360.0f; - public static final float RED = 0/360.0f; -/** - * would be 120 degrees, but we've cheated up toward cyan a bit for - * harmony. - */ - public static final float GREEN = 130.0f/360.0f; - public static final float ORANGE = 30.0f/360.0f; - public static final float MAGENTA = 312.0f/360.0f; -// public static final float MAGENTA = 300.0f/360.0f; - public static final float PURPLE = 280.0f/360.0f; -/** - * would be 240 degrees, but we've cheated down toward cyan a bit for - * legibility. - */ - public static final float BLUE = 215.0f/360.0f; - public static final float YELLOW_GREEN = 90.0f/360.0f; - public static final float RED_ORANGE = 15.0f/360.0f; - public static final float BLUE_MAGENTA = 270.0f/360.0f; - public static final float CYAN = 200.0f/360.0f; - public static final float YELLOW_ORANGE = 45.0f/360.0f; - public static final float RED_MAGENTA = 150.0f/360.0f; - -} +/* + * Copyright 1996-2002 by Andruid Kerne. All rights reserved. + * CONFIDENTIAL. Use is subject to license terms. + */ +package ecologylab.generic; + +/** + * Constants for RGB/Alpha and HSV color space operations. + */ +public interface Colors +{ + public static final int HUE = 0; + public static final int SAT = 1; + public static final int VAL = 2; + + public static final int ALPHA = 0xff000000; + public static final int RGB = 0xffffff; + public static final int R = 0xff0000; + public static final int G = 0xff00; + public static final int B = 0xff; + + public static final float YELLOW = 60.0f/360.0f; + public static final float RED = 0/360.0f; +/** + * would be 120 degrees, but we've cheated up toward cyan a bit for + * harmony. + */ + public static final float GREEN = 130.0f/360.0f; + public static final float ORANGE = 30.0f/360.0f; + public static final float MAGENTA = 312.0f/360.0f; +// public static final float MAGENTA = 300.0f/360.0f; + public static final float PURPLE = 280.0f/360.0f; +/** + * would be 240 degrees, but we've cheated down toward cyan a bit for + * legibility. + */ + public static final float BLUE = 215.0f/360.0f; + public static final float YELLOW_GREEN = 90.0f/360.0f; + public static final float RED_ORANGE = 15.0f/360.0f; + public static final float BLUE_MAGENTA = 270.0f/360.0f; + public static final float CYAN = 200.0f/360.0f; + public static final float YELLOW_ORANGE = 45.0f/360.0f; + public static final float RED_MAGENTA = 150.0f/360.0f; + +} diff --git a/simplCore/src/ecologylab/generic/ConfParser.java b/simplCore/src/ecologylab/generic/ConfParser.java index 737ffbb6..82a363a3 100644 --- a/simplCore/src/ecologylab/generic/ConfParser.java +++ b/simplCore/src/ecologylab/generic/ConfParser.java @@ -1,66 +1,66 @@ -package ecologylab.generic; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.HashMap; -import java.util.NoSuchElementException; -import java.util.Scanner; - - -public class ConfParser -{ - private File confFile; - private HashMap confMap; - - public ConfParser(File confFile) - { - this.confFile = confFile; - } - - public void setConfFile(File confFile) - { - this.confFile = confFile; - } - - public HashMap parse() throws FileNotFoundException - { - confMap = new HashMap(); - - if (!confFile.exists() || !confFile.canRead()) - { - System.err.println("Failed to parse conf file: " + confFile); - throw new FileNotFoundException(); - } - - //go line by line and add to the hash map if it's not a comment; - Scanner scanner = new Scanner(confFile); - scanner.useDelimiter("=|\\n"); - - while (scanner.hasNextLine()) - { - //ignore comments - if (scanner.findInLine("#") != null) - { - scanner.nextLine(); - continue; - } - - try - { - - String key = scanner.next().trim(); - - String value = scanner.next().trim(); - - System.out.println(key + ": " + value); - - confMap.put(key, value); - } catch (NoSuchElementException e) - { - break; - } - } - - return confMap; - } -} +package ecologylab.generic; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.HashMap; +import java.util.NoSuchElementException; +import java.util.Scanner; + + +public class ConfParser +{ + private File confFile; + private HashMap confMap; + + public ConfParser(File confFile) + { + this.confFile = confFile; + } + + public void setConfFile(File confFile) + { + this.confFile = confFile; + } + + public HashMap parse() throws FileNotFoundException + { + confMap = new HashMap(); + + if (!confFile.exists() || !confFile.canRead()) + { + System.err.println("Failed to parse conf file: " + confFile); + throw new FileNotFoundException(); + } + + //go line by line and add to the hash map if it's not a comment; + Scanner scanner = new Scanner(confFile); + scanner.useDelimiter("=|\\n"); + + while (scanner.hasNextLine()) + { + //ignore comments + if (scanner.findInLine("#") != null) + { + scanner.nextLine(); + continue; + } + + try + { + + String key = scanner.next().trim(); + + String value = scanner.next().trim(); + + System.out.println(key + ": " + value); + + confMap.put(key, value); + } catch (NoSuchElementException e) + { + break; + } + } + + return confMap; + } +} diff --git a/simplCore/src/ecologylab/generic/ConsoleUtils.java b/simplCore/src/ecologylab/generic/ConsoleUtils.java index ac18293a..8051379a 100644 --- a/simplCore/src/ecologylab/generic/ConsoleUtils.java +++ b/simplCore/src/ecologylab/generic/ConsoleUtils.java @@ -1,34 +1,34 @@ -package ecologylab.generic; - -/** - * Little group of utilities for making console debugging a little easier. - * - * @author blake - */ -public class ConsoleUtils extends Debug -{ - public static void obtrusiveConsoleOutput(String outputMessage, boolean stdErr) - { - if (stdErr) - { - System.err.println("****************************************************"); - System.err.println("----------------------------------------------------"); - System.err.println(outputMessage); - System.err.println("----------------------------------------------------"); - System.err.println("****************************************************"); - } - else - { - System.out.println("****************************************************"); - System.out.println("----------------------------------------------------"); - System.out.println(outputMessage); - System.out.println("----------------------------------------------------"); - System.out.println("****************************************************"); - } - } - - public static void obtrusiveConsoleOutput(String outputMessage) - { - obtrusiveConsoleOutput(outputMessage, false); - } -} +package ecologylab.generic; + +/** + * Little group of utilities for making console debugging a little easier. + * + * @author blake + */ +public class ConsoleUtils extends Debug +{ + public static void obtrusiveConsoleOutput(String outputMessage, boolean stdErr) + { + if (stdErr) + { + System.err.println("****************************************************"); + System.err.println("----------------------------------------------------"); + System.err.println(outputMessage); + System.err.println("----------------------------------------------------"); + System.err.println("****************************************************"); + } + else + { + System.out.println("****************************************************"); + System.out.println("----------------------------------------------------"); + System.out.println(outputMessage); + System.out.println("----------------------------------------------------"); + System.out.println("****************************************************"); + } + } + + public static void obtrusiveConsoleOutput(String outputMessage) + { + obtrusiveConsoleOutput(outputMessage, false); + } +} diff --git a/simplCore/src/ecologylab/generic/Continuation.java b/simplCore/src/ecologylab/generic/Continuation.java index 10bdb9a1..3a700ea1 100644 --- a/simplCore/src/ecologylab/generic/Continuation.java +++ b/simplCore/src/ecologylab/generic/Continuation.java @@ -1,27 +1,27 @@ -/* - * Copyright 1996-2002 by Andruid Kerne. All rights reserved. - * CONFIDENTIAL. Use is subject to license terms. - */ -package ecologylab.generic; - -/** - * DispatchTarget is a mechanism that enables non-linear flows of control around - * asynchronous tasks such as networked I/O. - *

- * In such cases, when an object makes a call to initiate an asynchronous operation, - * it passes itself to the service provider, as a DispatchTarget. - * Usually the result will be an immediate return, followed by a call to the - * delivery method at some later point in time. Usually, the service provider - * must guarantee that it will make such calls, even in cases of error. - */ -public interface Continuation -{ - /** - * Called, probably later asynchronously, when the requested service is complete. - * - * @param o -- enables an argument of any type to be passed back. - */ - // notification to the Client that event id is complete - public void callback(T o); -} - +/* + * Copyright 1996-2002 by Andruid Kerne. All rights reserved. + * CONFIDENTIAL. Use is subject to license terms. + */ +package ecologylab.generic; + +/** + * DispatchTarget is a mechanism that enables non-linear flows of control around + * asynchronous tasks such as networked I/O. + *

+ * In such cases, when an object makes a call to initiate an asynchronous operation, + * it passes itself to the service provider, as a DispatchTarget. + * Usually the result will be an immediate return, followed by a call to the + * delivery method at some later point in time. Usually, the service provider + * must guarantee that it will make such calls, even in cases of error. + */ +public interface Continuation +{ + /** + * Called, probably later asynchronously, when the requested service is complete. + * + * @param o -- enables an argument of any type to be passed back. + */ + // notification to the Client that event id is complete + public void callback(T o); +} + diff --git a/simplCore/src/ecologylab/generic/DataTransferTools.java b/simplCore/src/ecologylab/generic/DataTransferTools.java index 748376a2..7239634e 100644 --- a/simplCore/src/ecologylab/generic/DataTransferTools.java +++ b/simplCore/src/ecologylab/generic/DataTransferTools.java @@ -1,91 +1,91 @@ -package ecologylab.generic; - -import java.io.UnsupportedEncodingException; - - -/** - * Help for working with Sun's attrocious drag and drop and clipboard "support". - * - * @author andruid - */ -public class DataTransferTools extends Debug -{ - - public DataTransferTools() - { - super(); - - } - - static final String EOL = "\r\n"; - - static final String HTML_CLIPBOARD_FORMAT_HEADER = "Version:1.0"+ EOL + - "StartHTML:00000000000"+ EOL + - "EndHTML:00000000000"+ EOL + - "StartFragment:00000000000"+ EOL + - "EndFragment:00000000000" + EOL ; - - - static final int HEADER_LENGTH = HTML_CLIPBOARD_FORMAT_HEADER.length(); - - /** - * surrounds the html with this envelope, ready for - * windows clipboard (jdk support can be made better) - *

-	 * Version:1.0
-	 * StartHTML:00000000000
-	 * EndHTML:00000000000
-	 * StartFragment:00000000000
-	 * EndFragment:00000000000
-	 * <!--StartFragment-->
-	 * ...
-	 * <!-- EndFragment-- >
-	 * 
- * We have to return a byte array 'cause in Windows the html needs to be utf-8 - * encoded. And because we have to calculate char-offsets, we encode it here. - * @param html - * @return byte[] - */ - public static byte[] convertToMSCfHtml(String html) throws UnsupportedEncodingException - { - html = "" + html + "\r\n\0"; - - byte[] bHtml = html.getBytes("UTF-8");// encode first 'cause it may grow - int htmlLen = bHtml.length; - - StringBuffer buf = new StringBuffer(HTML_CLIPBOARD_FORMAT_HEADER); - setValueInHeader( buf, "StartHTML", HEADER_LENGTH-1); - setValueInHeader( buf, "EndHTML", HEADER_LENGTH + htmlLen-1); - setValueInHeader( buf, "StartFragment", HEADER_LENGTH-1); - setValueInHeader( buf, "EndFragment", HEADER_LENGTH + htmlLen-1); - byte[] bHeader = buf.toString().getBytes("UTF-8");// should stay the same (no nonASCII chars in header) - - byte result[] = new byte[HEADER_LENGTH + htmlLen ]; - System.arraycopy(bHeader, 0, result, 0, bHeader.length); - System.arraycopy(bHtml, 0, result, bHeader.length, bHtml.length); - - return result; - } - - /** - * Replaces name+":00000000000" with name+":xxxxxxxxxxx" where xxx... is the '0' padded value. - * Value can't be to long, since maxint can be displayed with 11 digits. If value is below zero - * there is enough place (10 for the digits 1 for sign).
- * If the search is not found nothing is done. - * @param src - * @param name - * @param value - */ - private static void setValueInHeader( StringBuffer src, String name, int value) - { - String search = name+":00000000000"; - int pos = src.indexOf(search); - if (pos ==-1) return;// not found, do nothing - - boolean belowZero = value<0; - if (belowZero) value = -value; - - src.replace(pos+search.length()-(value+"").length(), pos+search.length(), value+""); - if (belowZero) src.setCharAt(pos+name.length()+1,'-'); // +1 'cause of ':' in "SearchMe:" - } -} +package ecologylab.generic; + +import java.io.UnsupportedEncodingException; + + +/** + * Help for working with Sun's attrocious drag and drop and clipboard "support". + * + * @author andruid + */ +public class DataTransferTools extends Debug +{ + + public DataTransferTools() + { + super(); + + } + + static final String EOL = "\r\n"; + + static final String HTML_CLIPBOARD_FORMAT_HEADER = "Version:1.0"+ EOL + + "StartHTML:00000000000"+ EOL + + "EndHTML:00000000000"+ EOL + + "StartFragment:00000000000"+ EOL + + "EndFragment:00000000000" + EOL ; + + + static final int HEADER_LENGTH = HTML_CLIPBOARD_FORMAT_HEADER.length(); + + /** + * surrounds the html with this envelope, ready for + * windows clipboard (jdk support can be made better) + *
+	 * Version:1.0
+	 * StartHTML:00000000000
+	 * EndHTML:00000000000
+	 * StartFragment:00000000000
+	 * EndFragment:00000000000
+	 * <!--StartFragment-->
+	 * ...
+	 * <!-- EndFragment-- >
+	 * 
+ * We have to return a byte array 'cause in Windows the html needs to be utf-8 + * encoded. And because we have to calculate char-offsets, we encode it here. + * @param html + * @return byte[] + */ + public static byte[] convertToMSCfHtml(String html) throws UnsupportedEncodingException + { + html = "" + html + "\r\n\0"; + + byte[] bHtml = html.getBytes("UTF-8");// encode first 'cause it may grow + int htmlLen = bHtml.length; + + StringBuffer buf = new StringBuffer(HTML_CLIPBOARD_FORMAT_HEADER); + setValueInHeader( buf, "StartHTML", HEADER_LENGTH-1); + setValueInHeader( buf, "EndHTML", HEADER_LENGTH + htmlLen-1); + setValueInHeader( buf, "StartFragment", HEADER_LENGTH-1); + setValueInHeader( buf, "EndFragment", HEADER_LENGTH + htmlLen-1); + byte[] bHeader = buf.toString().getBytes("UTF-8");// should stay the same (no nonASCII chars in header) + + byte result[] = new byte[HEADER_LENGTH + htmlLen ]; + System.arraycopy(bHeader, 0, result, 0, bHeader.length); + System.arraycopy(bHtml, 0, result, bHeader.length, bHtml.length); + + return result; + } + + /** + * Replaces name+":00000000000" with name+":xxxxxxxxxxx" where xxx... is the '0' padded value. + * Value can't be to long, since maxint can be displayed with 11 digits. If value is below zero + * there is enough place (10 for the digits 1 for sign).
+ * If the search is not found nothing is done. + * @param src + * @param name + * @param value + */ + private static void setValueInHeader( StringBuffer src, String name, int value) + { + String search = name+":00000000000"; + int pos = src.indexOf(search); + if (pos ==-1) return;// not found, do nothing + + boolean belowZero = value<0; + if (belowZero) value = -value; + + src.replace(pos+search.length()-(value+"").length(), pos+search.length(), value+""); + if (belowZero) src.setCharAt(pos+name.length()+1,'-'); // +1 'cause of ':' in "SearchMe:" + } +} diff --git a/simplCore/src/ecologylab/generic/Debug.java b/simplCore/src/ecologylab/generic/Debug.java index 43dd75db..817379c1 100644 --- a/simplCore/src/ecologylab/generic/Debug.java +++ b/simplCore/src/ecologylab/generic/Debug.java @@ -1,595 +1,595 @@ -package ecologylab.generic; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.PrintStream; -import java.util.Date; -import java.util.HashMap; -import java.util.NoSuchElementException; -import java.util.StringTokenizer; - -import ecologylab.appframework.types.prefs.Pref; -import ecologylab.io.Files; - -/** - * A developer-friendly base class and toolset for logging debug messages. - * - * Supports a threshold, aka level with 2 levels of granularity: 1) global
- * 2) on a per class basis
- * - * This levels are configured via runtime startup params ( via the JavaScript prefs mechanisms for - * applet versions) - * - * in the form of 1) debug_global_level = 4; 2) debug_levels = "Parser 3; HTMLPage 2; CollageOp 37"; - * - * @author andruid - */ -public class Debug -{ - private static final String SEPARATOR = ": "; - - /** - * Global flag for printing "interactive debug" statements. See also {@link #debugI(String) - * debugI()}. - */ - private static boolean interactive; - - private static boolean logToFile = false; - - private static final HashMap, String> classAbbrevNames = new HashMap, String>(); - - private static final HashMap, String> packageNames = new HashMap, String>(); - - static final int FLUSH_FREQUENCY = 10; - - /** - * Holds class specific debug levels. - */ - static final HashMap classLevels = new HashMap(); - - /** - * Global hi watermark. debug() messages with a level less than or equal to this will get printed - * out. - */ - // private static PrefInt level = Pref.usePrefInt("debug_global_level", 0);; - - static final long initTimestamp = System.currentTimeMillis(); - - public static void initialize() - { - // class specific - String levels = Pref.lookupString("debug_levels"); - // println("Debug.initialize(" + Debug.level+", "+ levels+")"); - if (levels != null) - { - StringTokenizer tokenizer = new StringTokenizer(levels, ";"); - { - try - { - while (tokenizer.hasMoreTokens()) - { - String thisSpec = tokenizer.nextToken(); - StringTokenizer specTokenizer = new StringTokenizer(thisSpec); - try - { - String thisClassName = specTokenizer.nextToken(); - int thisLevel = Integer.parseInt(specTokenizer.nextToken()); - Debug.println("Debug.level\t" + thisClassName + "\t" + thisLevel); - classLevels.put(thisClassName, new IntSlot(thisLevel)); - } - catch (Exception e) - { - } - } - } - catch (NoSuchElementException e) - { - } - } - } - } - - protected Debug() - { - // AllocationDebugger.constructed(this); - } - - public final int level() - { - return level(this); - } - - public static final int level(Object that) - { - // return level(getClassName(that)); - return 0; - } - - public static final int level(String className) - { - /* - * int result = level.value(); IntSlot slot = (IntSlot) classLevels.get(className); if (slot != - * null) result = slot.value; return result; - */ - return 0; - } - - /** - * @param messageLevel - * If less than or equal to the static level, message will get logged. Otherwise, the - * statement will be ignored. - */ - // TODO make levels work again - public static void println(int messageLevel, CharSequence message) - { - // if (messageLevel <= level.value()) - // println(message); - } - - public static void printlnI(int messageLevel, CharSequence message) - { - if (interactive) - println(message); - } - - public static void println(Object o, CharSequence message) - { - print(o.toString()); - print(SEPARATOR); - println(message); - } - - public static void println(String className, CharSequence message) - { - print(className); - print(SEPARATOR); - println(message); - } - - public static void printlnI(Object o, CharSequence message) - { - if (interactive) - println(o, message); - } - - public static void printlnI(CharSequence message) - { - if (interactive) - println(message); - } - - /** - * Print the message to System.err. - *

- * If we are logging to a file, also write to the file, but in this case, prepend the Date: - * - * @param message - */ - public static void println(CharSequence message) - { - if (logToFile) - { - try - { - writer.append(new Date().toString()); - writer.append(':').append('\t'); - writer.append(message); - writer.append('\n'); - writer.flush(); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - else - System.out.println(message); - } - - public static void print(char c) - { - print(c, System.out); - } - - public static void print(char c, PrintStream pStream) - { - if (logToFile) - { - try - { - writer.append(c); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - else - pStream.print(c); - - } - - public static void print(CharSequence message) - { - print(message, System.out); - } - - public static void print(CharSequence message, PrintStream pStream) - { - if (logToFile) - { - try - { - writer.append(message); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - else - pStream.print(message); - } - - /** - * Print a debug message, starting with the abbreviated class name of the object. - */ - public static void printlnA(Object that, CharSequence message) - { - println(getClassSimpleName(that) + SEPARATOR + message/* +" " +level(that) */); - } - - /** - * Print a debug message, starting with the abbreviated class name. - */ - public static void printlnA(Class c, CharSequence message) - { - println(classSimpleName(c) + SEPARATOR + message); - } - - static char PERIOD = '.'; - - static char SPACE = ' '; - - /** - * This actually seems to be much more efficient than Class. getSimpleName(), because we are smart - * about using lazy evaluation and caching results in a HashMap. - * - * @return the abbreviated name of the class - without the package qualifier. - */ - public static String classSimpleName(Class thatClass) - { - String abbrevName = classAbbrevNames.get(thatClass); - if (abbrevName == null) - { - String fullName = thatClass.toString(); - abbrevName = fullName.substring(fullName.lastIndexOf(PERIOD) + 1); - synchronized (classAbbrevNames) - { - classAbbrevNames.put(thatClass, abbrevName); - } - } - return abbrevName; - } - - /** - * @return the abbreviated name of the class - without the package qualifier. - */ - public static String getPackageName(Class thatClass) - { - // System.out.println("thatClass.toString() is " + thatClass.toString()); - String packageName = packageNames.get(thatClass); - if (packageName == null) - { - String className = thatClass.toString(); - packageName = className.substring(className.indexOf(SPACE) + 1, className.lastIndexOf(PERIOD)); - synchronized (packageNames) - { - packageNames.put(thatClass, packageName); - // packageNames.put(className, packageName); - } - } - return packageName; - } - - /** - * @return the abbreviated name of the class - without the package qualifier. - */ - public static String getClassSimpleName(Object o) - { - return (o == null) ? "null" : classSimpleName(o.getClass()); - } - - /** - * @return the abbreviated name of this class - without the package qualifier. - */ - public String getClassSimpleName() - { - return getClassSimpleName(this); - } - - /** - * @return the package name of the class - without the package qualifier. - */ - public static String getPackageName(Object o) - { - return getPackageName(o.getClass()); - } - - /** - * @return the package name of this class - without the package qualifier. - */ - public String getPackageName() - { - return getPackageName(this); - } - - @Override - public String toString() - { - return getClassSimpleName(this); - } - - public String superString() - { - return super.toString(); - } - - public static String toString(Object o) - { - return getClassSimpleName(o); - } - - public final void debugT(CharSequence message) - { - debugT(this, message); - } - - public static final void debugT(Object that, CharSequence message) - { - // FIXME: This may be slow. Use sparingly - String tStamp = "{t=" + (System.currentTimeMillis() - initTimestamp) + "}"; - print(tStamp); - print(that.toString()); - println(message); - - } - - /** - * Print a debug message that starts with this.toString(). - */ - public final void debug(CharSequence message) - { - println(this, message); - } - - /** - * Print a message about an error, starting with this.toString(). - */ - public void error(CharSequence message) - { - error(this, message); - } - - /** - * Print a message about a warning, starting with this.toString(). - */ - public void warning(CharSequence message) - { - warning(this, message); - } - - /** - * Print a message about something that should never happen, starting with this.toString(). - */ - public void weird(CharSequence message) - { - weird(this, message); - } - - /** - * Print a message about an error, starting with that.toString(). - */ - public static void error(Object that, CharSequence message) - { - emphasized(that, "ERROR - ", message); - } - - /** - * Print a message with emphasis. - * - * @param that - * @param header - * @param message - */ - static void emphasized(Object that, String header, CharSequence message) - { - print('\n', System.err); - print(header, System.err); - print(that.toString(), System.err); - print(SEPARATOR, System.err); - print(' ', System.err); - print(message, System.err); - print('\n', System.err); - print('\n', System.err); - } - - /** - * Print a message about a warning, starting with that.toString(). - */ - public static void warning(Object that, CharSequence message) - { - emphasized(that, "WARNING - ", message); - } - - /** - * Print a message about something that should never happen, starting with that.toString(). - */ - public static void weird(Object that, CharSequence message) - { - emphasized(that, "WEIRD - ", message); - } - - /** - * Print a debug message that starts with this.toString(). - */ - public final void debug(StringBuffer message) - { - println(this, message); - } - - /** - * Print a debug message that starts with the abbreviated class name of this. - */ - public final void debugA(CharSequence message) - { - printlnA(this, message); - } - - /** - * Print a debug message that starts with the abbreviated class name of this. - */ - public final void debugA(StringBuffer message) - { - printlnA(this, message.toString()); - } - - public final void debugI(CharSequence message) - { - printlnI(this, message); - } - - public final void debugI(StringBuffer message) - { - printlnI(this, message.toString()); - } - - /** - * Evaluates the same conditional as Debug usually does implicitly, for explicit use in special - * static Debug printing scenarios. - **/ - public static final boolean show(Object that, int messageLevel) - { - return messageLevel <= level(that); - } - - public boolean show(int messageLevel) - { - return show(this, messageLevel); - } - - /** - * Print a debug message that starts with the abbreviated class name of this, but only if - * messageLevel is greater than the debug level for this class (see above). - */ - public final void debug(int messageLevel, CharSequence message) - { - // if (show(messageLevel)) - if (messageLevel <= level()) - println(this, message); - } - - public final void debugA(int messageLevel, CharSequence message) - { - if (messageLevel <= level()) - printlnA(this, message); - } - - public static final void println(Object that, int messageLevel, CharSequence message) - { - if (messageLevel <= level(that)) - println(that, message); - } - - public static final void println(String className, int messageLevel, CharSequence message) - { - if (messageLevel <= level(className)) - println(message); - } - - public static final void printlnA(Object that, int messageLevel, CharSequence message) - { - if (messageLevel <= level(that)) - printlnA(that, message); - } - - public static final void printlnI(Object that, int messageLevel, CharSequence message) - { - if (messageLevel <= level(that)) - printlnI(that, message); - } - - public final void debugI(int messageLevel, CharSequence message) - { - if (messageLevel <= level()) - printlnI(this, message); - } - - public static final void debug(Object o, CharSequence message, Exception e) - { - println(o, message); - e.printStackTrace(); - } - -// public static final void toggleInteractive() -// { -// interactive = !interactive; -// String msg = "Toggle interactive debug to " + interactive; -// Environment.the.get().status(msg); -// println(msg); -// } - - private static BufferedWriter writer; - - public static final void setLoggingFile(String loggingFilePath) - { - writer = Files.openWriter(loggingFilePath); - if (writer == null) - println("Debug.setLoggingFile() CANT OPEN LOGGING FILE: " + loggingFilePath); - else - logToFile = true; - } - - public static void closeLoggingFile() - { - Files.closeWriter(writer); - } - - /** - * @return state of the global flag for printing "interactive" debug statements. - */ - public static boolean getInteractive() - { - return interactive; - } - - public static boolean logToFile() - { - return logToFile; - } - // protected void finalize() - // { - // AllocationDebugger.finalized(this); - // } - - /** - * Check to make sure that condition is true. If not, throw an AssertionError. - * This is equivalent to assert, but added since assertion is often disabled by default, and - * thus ignored :( - * - * @param condition - * A condition that is expected to be true. - * @param format - * The format string of the message for the thrown exception. - * @param args - * The arguments to format. - */ - public static void check(boolean condition, String format, Object... args) - { - if (!condition) - { - throw new AssertionError(String.format(format, args)); - } - } - -} +package ecologylab.generic; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Date; +import java.util.HashMap; +import java.util.NoSuchElementException; +import java.util.StringTokenizer; + +import ecologylab.appframework.types.prefs.Pref; +import ecologylab.io.Files; + +/** + * A developer-friendly base class and toolset for logging debug messages. + * + * Supports a threshold, aka level with 2 levels of granularity: 1) global
+ * 2) on a per class basis
+ * + * This levels are configured via runtime startup params ( via the JavaScript prefs mechanisms for + * applet versions) + * + * in the form of 1) debug_global_level = 4; 2) debug_levels = "Parser 3; HTMLPage 2; CollageOp 37"; + * + * @author andruid + */ +public class Debug +{ + private static final String SEPARATOR = ": "; + + /** + * Global flag for printing "interactive debug" statements. See also {@link #debugI(String) + * debugI()}. + */ + private static boolean interactive; + + private static boolean logToFile = false; + + private static final HashMap, String> classAbbrevNames = new HashMap, String>(); + + private static final HashMap, String> packageNames = new HashMap, String>(); + + static final int FLUSH_FREQUENCY = 10; + + /** + * Holds class specific debug levels. + */ + static final HashMap classLevels = new HashMap(); + + /** + * Global hi watermark. debug() messages with a level less than or equal to this will get printed + * out. + */ + // private static PrefInt level = Pref.usePrefInt("debug_global_level", 0);; + + static final long initTimestamp = System.currentTimeMillis(); + + public static void initialize() + { + // class specific + String levels = Pref.lookupString("debug_levels"); + // println("Debug.initialize(" + Debug.level+", "+ levels+")"); + if (levels != null) + { + StringTokenizer tokenizer = new StringTokenizer(levels, ";"); + { + try + { + while (tokenizer.hasMoreTokens()) + { + String thisSpec = tokenizer.nextToken(); + StringTokenizer specTokenizer = new StringTokenizer(thisSpec); + try + { + String thisClassName = specTokenizer.nextToken(); + int thisLevel = Integer.parseInt(specTokenizer.nextToken()); + Debug.println("Debug.level\t" + thisClassName + "\t" + thisLevel); + classLevels.put(thisClassName, new IntSlot(thisLevel)); + } + catch (Exception e) + { + } + } + } + catch (NoSuchElementException e) + { + } + } + } + } + + protected Debug() + { + // AllocationDebugger.constructed(this); + } + + public final int level() + { + return level(this); + } + + public static final int level(Object that) + { + // return level(getClassName(that)); + return 0; + } + + public static final int level(String className) + { + /* + * int result = level.value(); IntSlot slot = (IntSlot) classLevels.get(className); if (slot != + * null) result = slot.value; return result; + */ + return 0; + } + + /** + * @param messageLevel + * If less than or equal to the static level, message will get logged. Otherwise, the + * statement will be ignored. + */ + // TODO make levels work again + public static void println(int messageLevel, CharSequence message) + { + // if (messageLevel <= level.value()) + // println(message); + } + + public static void printlnI(int messageLevel, CharSequence message) + { + if (interactive) + println(message); + } + + public static void println(Object o, CharSequence message) + { + print(o.toString()); + print(SEPARATOR); + println(message); + } + + public static void println(String className, CharSequence message) + { + print(className); + print(SEPARATOR); + println(message); + } + + public static void printlnI(Object o, CharSequence message) + { + if (interactive) + println(o, message); + } + + public static void printlnI(CharSequence message) + { + if (interactive) + println(message); + } + + /** + * Print the message to System.err. + *

+ * If we are logging to a file, also write to the file, but in this case, prepend the Date: + * + * @param message + */ + public static void println(CharSequence message) + { + if (logToFile) + { + try + { + writer.append(new Date().toString()); + writer.append(':').append('\t'); + writer.append(message); + writer.append('\n'); + writer.flush(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + else + System.out.println(message); + } + + public static void print(char c) + { + print(c, System.out); + } + + public static void print(char c, PrintStream pStream) + { + if (logToFile) + { + try + { + writer.append(c); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + else + pStream.print(c); + + } + + public static void print(CharSequence message) + { + print(message, System.out); + } + + public static void print(CharSequence message, PrintStream pStream) + { + if (logToFile) + { + try + { + writer.append(message); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + else + pStream.print(message); + } + + /** + * Print a debug message, starting with the abbreviated class name of the object. + */ + public static void printlnA(Object that, CharSequence message) + { + println(getClassSimpleName(that) + SEPARATOR + message/* +" " +level(that) */); + } + + /** + * Print a debug message, starting with the abbreviated class name. + */ + public static void printlnA(Class c, CharSequence message) + { + println(classSimpleName(c) + SEPARATOR + message); + } + + static char PERIOD = '.'; + + static char SPACE = ' '; + + /** + * This actually seems to be much more efficient than Class. getSimpleName(), because we are smart + * about using lazy evaluation and caching results in a HashMap. + * + * @return the abbreviated name of the class - without the package qualifier. + */ + public static String classSimpleName(Class thatClass) + { + String abbrevName = classAbbrevNames.get(thatClass); + if (abbrevName == null) + { + String fullName = thatClass.toString(); + abbrevName = fullName.substring(fullName.lastIndexOf(PERIOD) + 1); + synchronized (classAbbrevNames) + { + classAbbrevNames.put(thatClass, abbrevName); + } + } + return abbrevName; + } + + /** + * @return the abbreviated name of the class - without the package qualifier. + */ + public static String getPackageName(Class thatClass) + { + // System.out.println("thatClass.toString() is " + thatClass.toString()); + String packageName = packageNames.get(thatClass); + if (packageName == null) + { + String className = thatClass.toString(); + packageName = className.substring(className.indexOf(SPACE) + 1, className.lastIndexOf(PERIOD)); + synchronized (packageNames) + { + packageNames.put(thatClass, packageName); + // packageNames.put(className, packageName); + } + } + return packageName; + } + + /** + * @return the abbreviated name of the class - without the package qualifier. + */ + public static String getClassSimpleName(Object o) + { + return (o == null) ? "null" : classSimpleName(o.getClass()); + } + + /** + * @return the abbreviated name of this class - without the package qualifier. + */ + public String getClassSimpleName() + { + return getClassSimpleName(this); + } + + /** + * @return the package name of the class - without the package qualifier. + */ + public static String getPackageName(Object o) + { + return getPackageName(o.getClass()); + } + + /** + * @return the package name of this class - without the package qualifier. + */ + public String getPackageName() + { + return getPackageName(this); + } + + @Override + public String toString() + { + return getClassSimpleName(this); + } + + public String superString() + { + return super.toString(); + } + + public static String toString(Object o) + { + return getClassSimpleName(o); + } + + public final void debugT(CharSequence message) + { + debugT(this, message); + } + + public static final void debugT(Object that, CharSequence message) + { + // FIXME: This may be slow. Use sparingly + String tStamp = "{t=" + (System.currentTimeMillis() - initTimestamp) + "}"; + print(tStamp); + print(that.toString()); + println(message); + + } + + /** + * Print a debug message that starts with this.toString(). + */ + public final void debug(CharSequence message) + { + println(this, message); + } + + /** + * Print a message about an error, starting with this.toString(). + */ + public void error(CharSequence message) + { + error(this, message); + } + + /** + * Print a message about a warning, starting with this.toString(). + */ + public void warning(CharSequence message) + { + warning(this, message); + } + + /** + * Print a message about something that should never happen, starting with this.toString(). + */ + public void weird(CharSequence message) + { + weird(this, message); + } + + /** + * Print a message about an error, starting with that.toString(). + */ + public static void error(Object that, CharSequence message) + { + emphasized(that, "ERROR - ", message); + } + + /** + * Print a message with emphasis. + * + * @param that + * @param header + * @param message + */ + static void emphasized(Object that, String header, CharSequence message) + { + print('\n', System.err); + print(header, System.err); + print(that.toString(), System.err); + print(SEPARATOR, System.err); + print(' ', System.err); + print(message, System.err); + print('\n', System.err); + print('\n', System.err); + } + + /** + * Print a message about a warning, starting with that.toString(). + */ + public static void warning(Object that, CharSequence message) + { + emphasized(that, "WARNING - ", message); + } + + /** + * Print a message about something that should never happen, starting with that.toString(). + */ + public static void weird(Object that, CharSequence message) + { + emphasized(that, "WEIRD - ", message); + } + + /** + * Print a debug message that starts with this.toString(). + */ + public final void debug(StringBuffer message) + { + println(this, message); + } + + /** + * Print a debug message that starts with the abbreviated class name of this. + */ + public final void debugA(CharSequence message) + { + printlnA(this, message); + } + + /** + * Print a debug message that starts with the abbreviated class name of this. + */ + public final void debugA(StringBuffer message) + { + printlnA(this, message.toString()); + } + + public final void debugI(CharSequence message) + { + printlnI(this, message); + } + + public final void debugI(StringBuffer message) + { + printlnI(this, message.toString()); + } + + /** + * Evaluates the same conditional as Debug usually does implicitly, for explicit use in special + * static Debug printing scenarios. + **/ + public static final boolean show(Object that, int messageLevel) + { + return messageLevel <= level(that); + } + + public boolean show(int messageLevel) + { + return show(this, messageLevel); + } + + /** + * Print a debug message that starts with the abbreviated class name of this, but only if + * messageLevel is greater than the debug level for this class (see above). + */ + public final void debug(int messageLevel, CharSequence message) + { + // if (show(messageLevel)) + if (messageLevel <= level()) + println(this, message); + } + + public final void debugA(int messageLevel, CharSequence message) + { + if (messageLevel <= level()) + printlnA(this, message); + } + + public static final void println(Object that, int messageLevel, CharSequence message) + { + if (messageLevel <= level(that)) + println(that, message); + } + + public static final void println(String className, int messageLevel, CharSequence message) + { + if (messageLevel <= level(className)) + println(message); + } + + public static final void printlnA(Object that, int messageLevel, CharSequence message) + { + if (messageLevel <= level(that)) + printlnA(that, message); + } + + public static final void printlnI(Object that, int messageLevel, CharSequence message) + { + if (messageLevel <= level(that)) + printlnI(that, message); + } + + public final void debugI(int messageLevel, CharSequence message) + { + if (messageLevel <= level()) + printlnI(this, message); + } + + public static final void debug(Object o, CharSequence message, Exception e) + { + println(o, message); + e.printStackTrace(); + } + +// public static final void toggleInteractive() +// { +// interactive = !interactive; +// String msg = "Toggle interactive debug to " + interactive; +// Environment.the.get().status(msg); +// println(msg); +// } + + private static BufferedWriter writer; + + public static final void setLoggingFile(String loggingFilePath) + { + writer = Files.openWriter(loggingFilePath); + if (writer == null) + println("Debug.setLoggingFile() CANT OPEN LOGGING FILE: " + loggingFilePath); + else + logToFile = true; + } + + public static void closeLoggingFile() + { + Files.closeWriter(writer); + } + + /** + * @return state of the global flag for printing "interactive" debug statements. + */ + public static boolean getInteractive() + { + return interactive; + } + + public static boolean logToFile() + { + return logToFile; + } + // protected void finalize() + // { + // AllocationDebugger.finalized(this); + // } + + /** + * Check to make sure that condition is true. If not, throw an AssertionError. + * This is equivalent to assert, but added since assertion is often disabled by default, and + * thus ignored :( + * + * @param condition + * A condition that is expected to be true. + * @param format + * The format string of the message for the thrown exception. + * @param args + * The arguments to format. + */ + public static void check(boolean condition, String format, Object... args) + { + if (!condition) + { + throw new AssertionError(String.format(format, args)); + } + } + +} diff --git a/simplCore/src/ecologylab/generic/DebugMode.java b/simplCore/src/ecologylab/generic/DebugMode.java index b1c522e3..4df41164 100644 --- a/simplCore/src/ecologylab/generic/DebugMode.java +++ b/simplCore/src/ecologylab/generic/DebugMode.java @@ -1,18 +1,18 @@ -/** - * Interace for implementing an interactive console input debug mode for - * any class. - */ -package ecologylab.generic; - -/** - * Interace for implementing an interactive console input debug mode for - * any class. - * - * @author blake - */ -public interface DebugMode -{ - public void setDebugMode(boolean doDebug); - public void toggleDebugMode(); //inverts the debug mode - public boolean getDebugMode(); -} +/** + * Interace for implementing an interactive console input debug mode for + * any class. + */ +package ecologylab.generic; + +/** + * Interace for implementing an interactive console input debug mode for + * any class. + * + * @author blake + */ +public interface DebugMode +{ + public void setDebugMode(boolean doDebug); + public void toggleDebugMode(); //inverts the debug mode + public boolean getDebugMode(); +} diff --git a/simplCore/src/ecologylab/generic/Displacement1D.java b/simplCore/src/ecologylab/generic/Displacement1D.java index 20354631..67d7eed7 100644 --- a/simplCore/src/ecologylab/generic/Displacement1D.java +++ b/simplCore/src/ecologylab/generic/Displacement1D.java @@ -1,26 +1,26 @@ -package ecologylab.generic; - -/** - * defines a displacement in one dimension, of the form: - * a*x + b*width + c, - * where a=1, always, in our cases so far. - */ -public class Displacement1D -{ - int b, c; - - public Displacement1D(int[] v) - { - b = v[0]; - c = v[1]; - } - public Displacement1D(int b, int c) - { - this.b = b; - this.c = c; - } - public int xform(int q, int size) - { - return q + b*size + c; - } -} +package ecologylab.generic; + +/** + * defines a displacement in one dimension, of the form: + * a*x + b*width + c, + * where a=1, always, in our cases so far. + */ +public class Displacement1D +{ + int b, c; + + public Displacement1D(int[] v) + { + b = v[0]; + c = v[1]; + } + public Displacement1D(int b, int c) + { + this.b = b; + this.c = c; + } + public int xform(int q, int size) + { + return q + b*size + c; + } +} diff --git a/simplCore/src/ecologylab/generic/DoubleSlot.java b/simplCore/src/ecologylab/generic/DoubleSlot.java index 5457f283..b03153ad 100644 --- a/simplCore/src/ecologylab/generic/DoubleSlot.java +++ b/simplCore/src/ecologylab/generic/DoubleSlot.java @@ -1,26 +1,26 @@ -package ecologylab.generic; - -import ecologylab.serialization.ElementState; - -/** - * Reference version of a double type. Re-writable, unlike java.lang.Double. - */ -public class DoubleSlot extends ElementState -{ - public double value = 0; - - /** - * Used for ElementState. - * - */ - public DoubleSlot() - { - super(); - } - - public DoubleSlot(double d) - { - super(); - value = d; - } -} +package ecologylab.generic; + +import ecologylab.serialization.ElementState; + +/** + * Reference version of a double type. Re-writable, unlike java.lang.Double. + */ +public class DoubleSlot extends ElementState +{ + public double value = 0; + + /** + * Used for ElementState. + * + */ + public DoubleSlot() + { + super(); + } + + public DoubleSlot(double d) + { + super(); + value = d; + } +} diff --git a/simplCore/src/ecologylab/generic/ExceptionHandler.java b/simplCore/src/ecologylab/generic/ExceptionHandler.java index 812549a8..bb2ae096 100644 --- a/simplCore/src/ecologylab/generic/ExceptionHandler.java +++ b/simplCore/src/ecologylab/generic/ExceptionHandler.java @@ -1,26 +1,26 @@ -package ecologylab.generic; - -import ecologylab.collections.Scope; - -/** - * An exception handler used for callbacks. - * - * @author Blake Dworaczyk - */ -public abstract class ExceptionHandler -implements Runnable -{ - protected Exception exception; - protected Scope objectRegistry; - - public void handleException(Exception e, Scope objectRegistry) - { - this.exception = e; - this.objectRegistry = objectRegistry; - - Thread thread = new Thread(this); - thread.setPriority(10); - thread.run(); - } - -} +package ecologylab.generic; + +import ecologylab.collections.Scope; + +/** + * An exception handler used for callbacks. + * + * @author Blake Dworaczyk + */ +public abstract class ExceptionHandler +implements Runnable +{ + protected Exception exception; + protected Scope objectRegistry; + + public void handleException(Exception e, Scope objectRegistry) + { + this.exception = e; + this.objectRegistry = objectRegistry; + + Thread thread = new Thread(this); + thread.setPriority(10); + thread.run(); + } + +} diff --git a/simplCore/src/ecologylab/generic/FeatureVector.java b/simplCore/src/ecologylab/generic/FeatureVector.java index 9c48ea20..7b91610e 100644 --- a/simplCore/src/ecologylab/generic/FeatureVector.java +++ b/simplCore/src/ecologylab/generic/FeatureVector.java @@ -1,426 +1,426 @@ -package ecologylab.generic; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Observable; -import java.util.Set; - -public class FeatureVector extends Observable implements IFeatureVector -{ - - private static final int UNCALCULATED = -1; - - protected HashMap values; - - private double norm = UNCALCULATED, max = UNCALCULATED; - - private static final Map ZERO_LENGTH_HASHMAP = new HashMap(0); - - public FeatureVector () - { - } - - private void initValues() - { - values = new HashMap(); - } - - public FeatureVector ( int size ) - { - values = new HashMap(size); - } - - public FeatureVector ( IFeatureVector copyMe ) - { - Map otherMap = copyMe.map(); - if (otherMap != null && otherMap.size() > 0) - values = new HashMap(otherMap); - norm = copyMe.norm(); - } - - protected void reset() - { - if (values != null) - values.clear(); - resetNorm(); - } - - public FeatureVector copy ( ) - { - return new FeatureVector(this); - } - - @Override - public double get ( T term ) - { - if (values == null) - return 0; - - Double d = values.get(term); - if (d == null) - return 0; - return d; - } - - public void add ( T term, Double val ) - { - if (values == null) - initValues(); - - synchronized (values) - { - if (values.containsKey(term)) - val += values.get(term); - values.put(term, val); - resetNorm(); - } - } - - public void set ( T term, Double val ) - { - if (values == null) - initValues(); - - synchronized (values) - { - values.put(term, val); - resetNorm(); - } - } - - /** - * Pairwise multiplies this Vector by another Vector, in-place. - * - * @param v - * Vector by which to multiply - */ - public void multiply ( IFeatureVector v ) - { - Map other = v.map(); - if (other == null || values == null || other.size() == 0) - return; - synchronized (values) - { - this.values.keySet().retainAll(other.keySet()); - for (T term : this.values.keySet()) - this.values.put(term, other.get(term) * this.values.get(term)); - } - resetNorm(); - } - - /** - * Scalar multiplication of this vector by some constant - * - * @param c - * Constant to multiply this vector by. - */ - public void multiply ( double c ) - { - if (values == null) - return; - - synchronized (values) - { - ArrayList terms_to_delete = new ArrayList(); - for (T term : this.values.keySet()) - { - double new_val = c * this.values.get(term); - if (Math.abs(new_val) < 0.001) - terms_to_delete.add(term); - else - this.values.put(term, new_val); - } - for (T t : terms_to_delete) - values.remove(t); - } - resetNorm(); - } - - /** - * Pairwise addition of this vector by some other vector times some constant.
- * i.e. this + (c*v)
- * Vector v is not modified. - * - * @param c - * Constant which Vector v is multiplied by. - * @param v - * Vector to add to this one - */ - public void add ( double c, IFeatureVector v ) - { - Map other = v.map(); - - if (other == null || other.size() == 0) - return; - - if (values == null) - initValues(); - - synchronized (other) - { - synchronized (values) - { - for (T term : other.keySet()) - if (this.values.containsKey(term)) - this.values.put(term, new Double(c * other.get(term) + this.values.get(term))); - else - this.values.put(term, new Double(c * other.get(term))); - } - } - resetNorm(); - } - - /** - * Adds another Vector to this Vector, in-place. - * - * @param v - * Vector to add to this - */ - public void add ( IFeatureVector v ) - { - add(1, v); - } - - @Override - public double dot ( IFeatureVector v ) - { - return dot(v, false); - } - - public double dot ( IFeatureVector v, boolean simplex ) - { - Map other = v.map(); - if (other == null || other.size() == 0 || values == null || v.norm() == 0 || this.norm() == 0) - return 0; - - double dot = 0; - Map vector = this.values; - synchronized (values) - { - for (T term : vector.keySet()) - if (other.containsKey(term)) - if (simplex) - dot += vector.get(term); - else - dot += vector.get(term) + other.get(term); - } - return dot; - } - - @Override - public Set elements ( ) - { - if (values == null) - return new HashSet(0); - return new HashSet(values.keySet()); - } - - @Override - public Set values ( ) - { - if (values == null) - return new HashSet(0); - return new HashSet(values.values()); - } - /** - * Access to the inner-level HashMap backing this FeatureVector. - * Do NOT modify this collection outside of FeatureVector.java or TermVector.java, - * you will probably cause things to break. - * - * @return HashMap backing this FeatureVector - */ - @Override - public Map map ( ) - { - if (values == null) - return ZERO_LENGTH_HASHMAP; - return values; - } - - public int size ( ) - { - if (values == null) - return 0; - return values.size(); - } - - private void recalculateNorm ( ) - { - if (values == null) - return; - double norm = 0; - synchronized(values) - { - for (double d : this.values.values()) - { - norm += Math.pow(d, 2); - } - } - this.norm = Math.sqrt(norm); - } - - private void resetNorm ( ) - { - norm = UNCALCULATED; - max = UNCALCULATED; - } - - @Override - public double norm ( ) - { - if (norm == UNCALCULATED) - recalculateNorm(); - return norm; - } - - @Override - public double max ( ) - { - if (max == UNCALCULATED) - recalculateMax(); - return max; - } - - private void recalculateMax ( ) - { - if (values == null) - return; - - synchronized(values) - { - for (Double d : values.values()) - if (Math.abs(d) > max) - max = d; - } - } - - /** - * Linearly scales the vector such that the max value in the vector is no more than the passed - * in value.
- *
- * Pivots around zero so that negative values with a magnitude greater than the clamp will be - * scaled appropriately. - * - * @param clampTo - * The new max value of the vector. - */ - public void clamp ( double clampTo ) - { - if (values == null) - return; - - clampTo = Math.abs(clampTo); - double max = this.max(); - if (!(max > clampTo)) - return; - - double clampRatio = clampTo / max; - synchronized (values) - { - Set keySet = this.values.keySet(); - for (T term : keySet) - { - double old_value = this.values.get(term); - double new_value = clampRatio * old_value; - this.values.put(term, new_value); - } - } - resetNorm(); - } - - public void clampExp ( double clampTo ) - { - if (values == null) - return; - - clampTo = Math.abs(clampTo); - double max = 0; - synchronized (values) - { - for (Double d : values.values()) - { - double d2 = Math.abs(d); - if (d2 > max) - max = d2; - } - if (!(max > clampTo)) - return; - - ArrayList terms_to_delete = new ArrayList(); - for (T term : this.values.keySet()) - { - double old_value = this.values.get(term); - double new_value = clampTo * old_value / max; - if (Math.abs(new_value) < 0.001) - terms_to_delete.add(term); - else - this.values.put(term, new_value); - } - for (T t : terms_to_delete) - values.remove(t); - } - resetNorm(); - } - - @Override - public IFeatureVector unit ( ) - { - FeatureVector v = new FeatureVector(this); - v.clamp(1); - return v; - } - - @Override - public double dotSimplex ( IFeatureVector v ) - { - return dot(v, true); - } - - @Override - public int commonDimensions ( IFeatureVector v ) - { - Set v_elements = v.elements(); - v_elements.retainAll(this.elements()); - return v_elements.size(); - } - - @Override - public FeatureVector simplex ( ) - { - FeatureVector v = new FeatureVector(this); - for (T t : v.values.keySet()) - { - v.values.put(t, 1.0); - } - return v; - } - - public void clear() - { - if (values == null) - return; - - synchronized(values) - { - values.clear(); - } - } - - public void recycle() - { - if (values != null) - { - values.clear(); - values = null;//TODO could drop this line to be more moderate - } - } - - @Override - public boolean isRecycled() - { - return values == null; - } - -} +package ecologylab.generic; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Observable; +import java.util.Set; + +public class FeatureVector extends Observable implements IFeatureVector +{ + + private static final int UNCALCULATED = -1; + + protected HashMap values; + + private double norm = UNCALCULATED, max = UNCALCULATED; + + private static final Map ZERO_LENGTH_HASHMAP = new HashMap(0); + + public FeatureVector () + { + } + + private void initValues() + { + values = new HashMap(); + } + + public FeatureVector ( int size ) + { + values = new HashMap(size); + } + + public FeatureVector ( IFeatureVector copyMe ) + { + Map otherMap = copyMe.map(); + if (otherMap != null && otherMap.size() > 0) + values = new HashMap(otherMap); + norm = copyMe.norm(); + } + + protected void reset() + { + if (values != null) + values.clear(); + resetNorm(); + } + + public FeatureVector copy ( ) + { + return new FeatureVector(this); + } + + @Override + public double get ( T term ) + { + if (values == null) + return 0; + + Double d = values.get(term); + if (d == null) + return 0; + return d; + } + + public void add ( T term, Double val ) + { + if (values == null) + initValues(); + + synchronized (values) + { + if (values.containsKey(term)) + val += values.get(term); + values.put(term, val); + resetNorm(); + } + } + + public void set ( T term, Double val ) + { + if (values == null) + initValues(); + + synchronized (values) + { + values.put(term, val); + resetNorm(); + } + } + + /** + * Pairwise multiplies this Vector by another Vector, in-place. + * + * @param v + * Vector by which to multiply + */ + public void multiply ( IFeatureVector v ) + { + Map other = v.map(); + if (other == null || values == null || other.size() == 0) + return; + synchronized (values) + { + this.values.keySet().retainAll(other.keySet()); + for (T term : this.values.keySet()) + this.values.put(term, other.get(term) * this.values.get(term)); + } + resetNorm(); + } + + /** + * Scalar multiplication of this vector by some constant + * + * @param c + * Constant to multiply this vector by. + */ + public void multiply ( double c ) + { + if (values == null) + return; + + synchronized (values) + { + ArrayList terms_to_delete = new ArrayList(); + for (T term : this.values.keySet()) + { + double new_val = c * this.values.get(term); + if (Math.abs(new_val) < 0.001) + terms_to_delete.add(term); + else + this.values.put(term, new_val); + } + for (T t : terms_to_delete) + values.remove(t); + } + resetNorm(); + } + + /** + * Pairwise addition of this vector by some other vector times some constant.
+ * i.e. this + (c*v)
+ * Vector v is not modified. + * + * @param c + * Constant which Vector v is multiplied by. + * @param v + * Vector to add to this one + */ + public void add ( double c, IFeatureVector v ) + { + Map other = v.map(); + + if (other == null || other.size() == 0) + return; + + if (values == null) + initValues(); + + synchronized (other) + { + synchronized (values) + { + for (T term : other.keySet()) + if (this.values.containsKey(term)) + this.values.put(term, new Double(c * other.get(term) + this.values.get(term))); + else + this.values.put(term, new Double(c * other.get(term))); + } + } + resetNorm(); + } + + /** + * Adds another Vector to this Vector, in-place. + * + * @param v + * Vector to add to this + */ + public void add ( IFeatureVector v ) + { + add(1, v); + } + + @Override + public double dot ( IFeatureVector v ) + { + return dot(v, false); + } + + public double dot ( IFeatureVector v, boolean simplex ) + { + Map other = v.map(); + if (other == null || other.size() == 0 || values == null || v.norm() == 0 || this.norm() == 0) + return 0; + + double dot = 0; + Map vector = this.values; + synchronized (values) + { + for (T term : vector.keySet()) + if (other.containsKey(term)) + if (simplex) + dot += vector.get(term); + else + dot += vector.get(term) + other.get(term); + } + return dot; + } + + @Override + public Set elements ( ) + { + if (values == null) + return new HashSet(0); + return new HashSet(values.keySet()); + } + + @Override + public Set values ( ) + { + if (values == null) + return new HashSet(0); + return new HashSet(values.values()); + } + /** + * Access to the inner-level HashMap backing this FeatureVector. + * Do NOT modify this collection outside of FeatureVector.java or TermVector.java, + * you will probably cause things to break. + * + * @return HashMap backing this FeatureVector + */ + @Override + public Map map ( ) + { + if (values == null) + return ZERO_LENGTH_HASHMAP; + return values; + } + + public int size ( ) + { + if (values == null) + return 0; + return values.size(); + } + + private void recalculateNorm ( ) + { + if (values == null) + return; + double norm = 0; + synchronized(values) + { + for (double d : this.values.values()) + { + norm += Math.pow(d, 2); + } + } + this.norm = Math.sqrt(norm); + } + + private void resetNorm ( ) + { + norm = UNCALCULATED; + max = UNCALCULATED; + } + + @Override + public double norm ( ) + { + if (norm == UNCALCULATED) + recalculateNorm(); + return norm; + } + + @Override + public double max ( ) + { + if (max == UNCALCULATED) + recalculateMax(); + return max; + } + + private void recalculateMax ( ) + { + if (values == null) + return; + + synchronized(values) + { + for (Double d : values.values()) + if (Math.abs(d) > max) + max = d; + } + } + + /** + * Linearly scales the vector such that the max value in the vector is no more than the passed + * in value.
+ *
+ * Pivots around zero so that negative values with a magnitude greater than the clamp will be + * scaled appropriately. + * + * @param clampTo + * The new max value of the vector. + */ + public void clamp ( double clampTo ) + { + if (values == null) + return; + + clampTo = Math.abs(clampTo); + double max = this.max(); + if (!(max > clampTo)) + return; + + double clampRatio = clampTo / max; + synchronized (values) + { + Set keySet = this.values.keySet(); + for (T term : keySet) + { + double old_value = this.values.get(term); + double new_value = clampRatio * old_value; + this.values.put(term, new_value); + } + } + resetNorm(); + } + + public void clampExp ( double clampTo ) + { + if (values == null) + return; + + clampTo = Math.abs(clampTo); + double max = 0; + synchronized (values) + { + for (Double d : values.values()) + { + double d2 = Math.abs(d); + if (d2 > max) + max = d2; + } + if (!(max > clampTo)) + return; + + ArrayList terms_to_delete = new ArrayList(); + for (T term : this.values.keySet()) + { + double old_value = this.values.get(term); + double new_value = clampTo * old_value / max; + if (Math.abs(new_value) < 0.001) + terms_to_delete.add(term); + else + this.values.put(term, new_value); + } + for (T t : terms_to_delete) + values.remove(t); + } + resetNorm(); + } + + @Override + public IFeatureVector unit ( ) + { + FeatureVector v = new FeatureVector(this); + v.clamp(1); + return v; + } + + @Override + public double dotSimplex ( IFeatureVector v ) + { + return dot(v, true); + } + + @Override + public int commonDimensions ( IFeatureVector v ) + { + Set v_elements = v.elements(); + v_elements.retainAll(this.elements()); + return v_elements.size(); + } + + @Override + public FeatureVector simplex ( ) + { + FeatureVector v = new FeatureVector(this); + for (T t : v.values.keySet()) + { + v.values.put(t, 1.0); + } + return v; + } + + public void clear() + { + if (values == null) + return; + + synchronized(values) + { + values.clear(); + } + } + + public void recycle() + { + if (values != null) + { + values.clear(); + values = null;//TODO could drop this line to be more moderate + } + } + + @Override + public boolean isRecycled() + { + return values == null; + } + +} diff --git a/simplCore/src/ecologylab/generic/FloatSlot.java b/simplCore/src/ecologylab/generic/FloatSlot.java index 1106fa2a..e87cda3e 100644 --- a/simplCore/src/ecologylab/generic/FloatSlot.java +++ b/simplCore/src/ecologylab/generic/FloatSlot.java @@ -1,16 +1,16 @@ -package ecologylab.generic; - - -/** - * Reference version of a float type. Re-writable, unlike java.lang.Float. - */ -public class FloatSlot -extends Object -{ - public float value; - public FloatSlot(float b) - { - super(); - value = b; - } -} +package ecologylab.generic; + + +/** + * Reference version of a float type. Re-writable, unlike java.lang.Float. + */ +public class FloatSlot +extends Object +{ + public float value; + public FloatSlot(float b) + { + super(); + value = b; + } +} diff --git a/simplCore/src/ecologylab/generic/Generic.java b/simplCore/src/ecologylab/generic/Generic.java index 6175ad53..89ffdea8 100644 --- a/simplCore/src/ecologylab/generic/Generic.java +++ b/simplCore/src/ecologylab/generic/Generic.java @@ -1,301 +1,301 @@ -package ecologylab.generic; - -import ecologylab.platformspecifics.FundamentalPlatformSpecifics; - -//import java.awt.Toolkit; - -//import javax.swing.JOptionPane; - - -/** - * A set of generic convenience methods for doing things like getting - * typed parameters from the environment, getting other stuff from - * the environment, building HashMaps from arrays, manipulating threads, - * ... While some of these functionalities constitute a nice set of static - * covers for facilities provided by {@link Environment Environment}, - * this class can be viewed as a kitchen sink of useful static methods. - * - * @author andruid - */ -public class Generic -{ -/** - * Convert a String to a boolean. - * - * @param value - * @return true if the String is "true", "yes", or "1". - * false otherwise - */ - public static boolean booleanFromString(String value) - { - return value.equalsIgnoreCase("true") || - value.equalsIgnoreCase("yes") || value.equals("1"); - } - /** - * Turn a string into a float. - * - * @return the float, if the String is cool; else Float.NaN - */ - static public float parseFloat(String floatString) - { - float result; - try - { - Double fObj = Double.valueOf(floatString); - result = fObj.floatValue(); - } catch (NumberFormatException e) - { - result = Float.NaN; - } - return result; - } - - -/** - * Sleep easily. - * Report InterruptedExceptions when they happen, - * if the param is true. - */ - public static final void sleep(int time) - { - sleep(time, true); - } - -/** - * Sleep easily. - * Report InterruptedExceptions when they happen, - * if the param is true. - */ - public static final void sleep(int time, boolean reportExceptions) - { - try - { - Thread.sleep(time); - } - catch (InterruptedException e) - { - if (reportExceptions) - { - Debug.println("Sleep was interrupted -- clearing if possible."); - e.printStackTrace(); - } - // in jdk 1.1x clears the interrupt - // !!! (undocumented) !!! (see Thread src) - Thread.interrupted(); - } - } - - public static final String SEP = "/"; - - /** - * Set the priority of the current thread. - */ - static final public void setPriority(int priority) - { - setPriority(Thread.currentThread(), priority); - } -/** - * Set the priority of the current thread. - */ - static final public void setPriority(Thread t, int priority) - { - int oldPriority = t.getPriority(); - if (oldPriority != priority) - t.setPriority(priority); - } - - ////////////////////////////////////////////////////////////// - public static String round(float f, int powerOfTen) - { - if (Float.isNaN(f)) - return "NaN"; - int i = (int) f; - if ((f - i) == 0) - { - return Integer.toString(i); - } - String input = Float.toString(f); - // Debug.println("input="+input+" powerOfTen="+powerOfTen); - int end = input.length(); - int dot = input.indexOf('.'); - int exp = input.indexOf('E'); - int endFigs = (exp <= 0) ? end : exp; - int figs = endFigs - dot; - // Debug.println("dot="+dot+" exp="+exp+" figs="+figs+" endFigs="+endFigs); - String result = input; - if (figs > powerOfTen) - { - result = input.substring(0, dot+powerOfTen+1); - if (exp > 0) - result += input.substring(exp); - } - return result ; - } - - /** - * Raise the priority of the current thread to the priority level, - * if the current priority level is less than it. - * Otherwise, do nothing. - * - * @param priority - */ - public static void raisePriority(int priority) - { - Thread t = Thread.currentThread(); - int oldPriority = t.getPriority(); - if (oldPriority < priority) - { - raiseMaxPriority(t, priority); - t.setPriority(priority); - //Debug.println("\nraisingPriority{" + t + "} " + oldPriority +" -> "+ - //t.getPriority()); - } - } - public static void raiseMaxPriority(int priority) - { - raiseMaxPriority(Thread.currentThread(), priority); - } - public static void raiseMaxPriority(Thread thread, int priority) - { - raiseMaxPriority(thread.getThreadGroup(), priority); - } - public static void raiseMaxPriority(ThreadGroup threadGroup, int priority) - { - int oldMaxPriority = threadGroup.getMaxPriority(); - if (oldMaxPriority < priority) - { - ThreadGroup parent = threadGroup.getParent(); - if (parent != null) - raiseMaxPriority(parent, priority); // recurse - - threadGroup.setMaxPriority(priority); - Debug.println("\nraisingMaxPriority to " + priority+"->"+ - threadGroup.getMaxPriority()+ - " "+threadGroup+ " "+parent); - } - } - public static ThreadGroup findThreadGroup(int priority) - { - return findThreadGroup(Thread.currentThread(), priority); - } - public static ThreadGroup findThreadGroup(Thread thread, - int priority) - { - return findThreadGroup(thread.getThreadGroup(), priority); - } - public static ThreadGroup findThreadGroup(ThreadGroup threadGroup, - int priority) - { - int maxPriority = threadGroup.getMaxPriority(); - if (maxPriority < priority) - { - ThreadGroup parent = null; - try - { - parent = threadGroup.getParent(); - } catch (java.security.AccessControlException e) - { // (damn macintosh!) - Debug.println("ERROR manipulating thread groups!"); - e.printStackTrace(); - } - if (parent != null) - return findThreadGroup(parent, priority); // recurse - else - return null; - } - else - { - Debug.println("found " + threadGroup+" w maxPriority="+maxPriority); - return threadGroup; - } - } -/** - * @return the int represented by input. - * Silently defaults to defaultVal, input is - * not in good form. - */ - public static final int parseInt(String input, int defaultVal) - { - if (input != null) - { - try - { - defaultVal = Integer.parseInt(input); - } catch (NumberFormatException e) - { - } - } - return defaultVal; - } - - public static void main(String[] s) - { - Debug.println(round(LN_EMPTY_WEIGHT, 2)); - Debug.println(round(.334455f, 3)); - Debug.println(round(-.334455f, 3)); - Debug.println(round(22, 3)); - } - static final float LN_EMPTY_WEIGHT = Float.MAX_VALUE / 1000; - - public static void beep() - { - FundamentalPlatformSpecifics.get().beep(); - } - -/** - * Find the first object equal to the one passed in as the second argument, - * within the List that is the first argument. - * - * @param list The list to search. - * @param object The object to look for. Must not be null. - * - * @return The equal object from the list, if there is one, or null. - */ - static public Object findEqual(java.util.List list, Object object) - { - synchronized (list) - { - int size = list.size(); - for (int i=0; i 7) - s = s.substring(0,7); - return s; - } -} +package ecologylab.generic; + +import ecologylab.platformspecifics.FundamentalPlatformSpecifics; + +//import java.awt.Toolkit; + +//import javax.swing.JOptionPane; + + +/** + * A set of generic convenience methods for doing things like getting + * typed parameters from the environment, getting other stuff from + * the environment, building HashMaps from arrays, manipulating threads, + * ... While some of these functionalities constitute a nice set of static + * covers for facilities provided by {@link Environment Environment}, + * this class can be viewed as a kitchen sink of useful static methods. + * + * @author andruid + */ +public class Generic +{ +/** + * Convert a String to a boolean. + * + * @param value + * @return true if the String is "true", "yes", or "1". + * false otherwise + */ + public static boolean booleanFromString(String value) + { + return value.equalsIgnoreCase("true") || + value.equalsIgnoreCase("yes") || value.equals("1"); + } + /** + * Turn a string into a float. + * + * @return the float, if the String is cool; else Float.NaN + */ + static public float parseFloat(String floatString) + { + float result; + try + { + Double fObj = Double.valueOf(floatString); + result = fObj.floatValue(); + } catch (NumberFormatException e) + { + result = Float.NaN; + } + return result; + } + + +/** + * Sleep easily. + * Report InterruptedExceptions when they happen, + * if the param is true. + */ + public static final void sleep(int time) + { + sleep(time, true); + } + +/** + * Sleep easily. + * Report InterruptedExceptions when they happen, + * if the param is true. + */ + public static final void sleep(int time, boolean reportExceptions) + { + try + { + Thread.sleep(time); + } + catch (InterruptedException e) + { + if (reportExceptions) + { + Debug.println("Sleep was interrupted -- clearing if possible."); + e.printStackTrace(); + } + // in jdk 1.1x clears the interrupt + // !!! (undocumented) !!! (see Thread src) + Thread.interrupted(); + } + } + + public static final String SEP = "/"; + + /** + * Set the priority of the current thread. + */ + static final public void setPriority(int priority) + { + setPriority(Thread.currentThread(), priority); + } +/** + * Set the priority of the current thread. + */ + static final public void setPriority(Thread t, int priority) + { + int oldPriority = t.getPriority(); + if (oldPriority != priority) + t.setPriority(priority); + } + + ////////////////////////////////////////////////////////////// + public static String round(float f, int powerOfTen) + { + if (Float.isNaN(f)) + return "NaN"; + int i = (int) f; + if ((f - i) == 0) + { + return Integer.toString(i); + } + String input = Float.toString(f); + // Debug.println("input="+input+" powerOfTen="+powerOfTen); + int end = input.length(); + int dot = input.indexOf('.'); + int exp = input.indexOf('E'); + int endFigs = (exp <= 0) ? end : exp; + int figs = endFigs - dot; + // Debug.println("dot="+dot+" exp="+exp+" figs="+figs+" endFigs="+endFigs); + String result = input; + if (figs > powerOfTen) + { + result = input.substring(0, dot+powerOfTen+1); + if (exp > 0) + result += input.substring(exp); + } + return result ; + } + + /** + * Raise the priority of the current thread to the priority level, + * if the current priority level is less than it. + * Otherwise, do nothing. + * + * @param priority + */ + public static void raisePriority(int priority) + { + Thread t = Thread.currentThread(); + int oldPriority = t.getPriority(); + if (oldPriority < priority) + { + raiseMaxPriority(t, priority); + t.setPriority(priority); + //Debug.println("\nraisingPriority{" + t + "} " + oldPriority +" -> "+ + //t.getPriority()); + } + } + public static void raiseMaxPriority(int priority) + { + raiseMaxPriority(Thread.currentThread(), priority); + } + public static void raiseMaxPriority(Thread thread, int priority) + { + raiseMaxPriority(thread.getThreadGroup(), priority); + } + public static void raiseMaxPriority(ThreadGroup threadGroup, int priority) + { + int oldMaxPriority = threadGroup.getMaxPriority(); + if (oldMaxPriority < priority) + { + ThreadGroup parent = threadGroup.getParent(); + if (parent != null) + raiseMaxPriority(parent, priority); // recurse + + threadGroup.setMaxPriority(priority); + Debug.println("\nraisingMaxPriority to " + priority+"->"+ + threadGroup.getMaxPriority()+ + " "+threadGroup+ " "+parent); + } + } + public static ThreadGroup findThreadGroup(int priority) + { + return findThreadGroup(Thread.currentThread(), priority); + } + public static ThreadGroup findThreadGroup(Thread thread, + int priority) + { + return findThreadGroup(thread.getThreadGroup(), priority); + } + public static ThreadGroup findThreadGroup(ThreadGroup threadGroup, + int priority) + { + int maxPriority = threadGroup.getMaxPriority(); + if (maxPriority < priority) + { + ThreadGroup parent = null; + try + { + parent = threadGroup.getParent(); + } catch (java.security.AccessControlException e) + { // (damn macintosh!) + Debug.println("ERROR manipulating thread groups!"); + e.printStackTrace(); + } + if (parent != null) + return findThreadGroup(parent, priority); // recurse + else + return null; + } + else + { + Debug.println("found " + threadGroup+" w maxPriority="+maxPriority); + return threadGroup; + } + } +/** + * @return the int represented by input. + * Silently defaults to defaultVal, input is + * not in good form. + */ + public static final int parseInt(String input, int defaultVal) + { + if (input != null) + { + try + { + defaultVal = Integer.parseInt(input); + } catch (NumberFormatException e) + { + } + } + return defaultVal; + } + + public static void main(String[] s) + { + Debug.println(round(LN_EMPTY_WEIGHT, 2)); + Debug.println(round(.334455f, 3)); + Debug.println(round(-.334455f, 3)); + Debug.println(round(22, 3)); + } + static final float LN_EMPTY_WEIGHT = Float.MAX_VALUE / 1000; + + public static void beep() + { + FundamentalPlatformSpecifics.get().beep(); + } + +/** + * Find the first object equal to the one passed in as the second argument, + * within the List that is the first argument. + * + * @param list The list to search. + * @param object The object to look for. Must not be null. + * + * @return The equal object from the list, if there is one, or null. + */ + static public Object findEqual(java.util.List list, Object object) + { + synchronized (list) + { + int size = list.size(); + for (int i=0; i 7) + s = s.substring(0,7); + return s; + } +} diff --git a/simplCore/src/ecologylab/generic/HashMapArrayList.java b/simplCore/src/ecologylab/generic/HashMapArrayList.java index e918743f..17d1fcf5 100644 --- a/simplCore/src/ecologylab/generic/HashMapArrayList.java +++ b/simplCore/src/ecologylab/generic/HashMapArrayList.java @@ -1,114 +1,114 @@ -/** - * - */ -package ecologylab.generic; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -/** - * A HashMap with an ArrayList backing store, for speedy linear and hashed access. - * - * @author andruid - * - */ -public class HashMapArrayList extends HashMap implements Iterable -{ - protected final ArrayList arrayList; - - /** - * - */ - public HashMapArrayList() - { - arrayList = new ArrayList(); - } - - /** - * @param arg0 - */ - public HashMapArrayList(int arg0) - { - super(arg0); - arrayList = new ArrayList(arg0); - } - - /** - * @param arg0 - */ - public HashMapArrayList(Map arg0) - { - super(arg0); - arrayList = new ArrayList(arg0.size()); - } - - /** - * @param arg0 - * @param arg1 - */ - public HashMapArrayList(int arg0, float arg1) - { - super(arg0, arg1); - arrayList = new ArrayList(arg0); - } - - @Override public V put(K key, V value) - { - V result = super.put(key, value); - if (result != null) // the object that was overridden - arrayList.remove(result); - arrayList.add(value); - - return result; - } - - @Override public void putAll(Map map) - { - for (K key : map.keySet()) - this.put(key, map.get(key)); - } - - public V get(int index) - { - return arrayList.get(index); - } - - @Override - public Iterator iterator() - { - return arrayList.iterator(); - } - - @Override public V remove(Object key) - { - V result = super.remove(key); - if (result != null) - arrayList.remove(result); - return result; - } - - @Override public void clear() - { - super.clear(); - arrayList.clear(); - } - - public void recycle() - { - super.clear(); - int last = arrayList.size() - 1; - for (int i=last; i>=0; i--) - { - V that = arrayList.remove(i); - // that.recycle() -- must enforce that implements Recyclable - } - } - - @Override public Collection values() - { - return arrayList; - } -} +/** + * + */ +package ecologylab.generic; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * A HashMap with an ArrayList backing store, for speedy linear and hashed access. + * + * @author andruid + * + */ +public class HashMapArrayList extends HashMap implements Iterable +{ + protected final ArrayList arrayList; + + /** + * + */ + public HashMapArrayList() + { + arrayList = new ArrayList(); + } + + /** + * @param arg0 + */ + public HashMapArrayList(int arg0) + { + super(arg0); + arrayList = new ArrayList(arg0); + } + + /** + * @param arg0 + */ + public HashMapArrayList(Map arg0) + { + super(arg0); + arrayList = new ArrayList(arg0.size()); + } + + /** + * @param arg0 + * @param arg1 + */ + public HashMapArrayList(int arg0, float arg1) + { + super(arg0, arg1); + arrayList = new ArrayList(arg0); + } + + @Override public V put(K key, V value) + { + V result = super.put(key, value); + if (result != null) // the object that was overridden + arrayList.remove(result); + arrayList.add(value); + + return result; + } + + @Override public void putAll(Map map) + { + for (K key : map.keySet()) + this.put(key, map.get(key)); + } + + public V get(int index) + { + return arrayList.get(index); + } + + @Override + public Iterator iterator() + { + return arrayList.iterator(); + } + + @Override public V remove(Object key) + { + V result = super.remove(key); + if (result != null) + arrayList.remove(result); + return result; + } + + @Override public void clear() + { + super.clear(); + arrayList.clear(); + } + + public void recycle() + { + super.clear(); + int last = arrayList.size() - 1; + for (int i=last; i>=0; i--) + { + V that = arrayList.remove(i); + // that.recycle() -- must enforce that implements Recyclable + } + } + + @Override public Collection values() + { + return arrayList; + } +} diff --git a/simplCore/src/ecologylab/generic/HashMapWriteSynch.java b/simplCore/src/ecologylab/generic/HashMapWriteSynch.java index c58220b5..3a188dad 100644 --- a/simplCore/src/ecologylab/generic/HashMapWriteSynch.java +++ b/simplCore/src/ecologylab/generic/HashMapWriteSynch.java @@ -1,76 +1,76 @@ -package ecologylab.generic; - -import java.util.Map; - -/** - * Hashed data structure with synchronized writes/deletes and unsynchronized reads. - * - * @author andruid, robinson - * - * @param - * @param - */ -public class HashMapWriteSynch extends HashMapWriteSynchBase -{ - final ValueFactory factory; - - public HashMapWriteSynch(ValueFactory factory, int arg0, float arg1) - { - super(arg0, arg1); - this.factory = factory; - } - - public HashMapWriteSynch(ValueFactory factory, int arg0) - { - super(arg0); - this.factory = factory; - } - - public HashMapWriteSynch(ValueFactory factory) - { - super(); - this.factory = factory; - } - - public HashMapWriteSynch(ValueFactory factory, Map arg0) - { - super(arg0); - this.factory = factory; - } - - /** - * If there is already an entry, return it. - * - * Otherwise, create an entry with the factory. - * - * @return The entry matching key, found or constructed. - */ - public V getOrConstruct(K key) - { - V result = get(key); - if (result == null) - { - synchronized (this) - { - result = get(key); - if (result == null) - { - result = factory.constructValue(key); - super.put(key, result); - } - } - } - return result; - } - - - @Override - public V put(K key, V value) - { - synchronized(this) - { - return super.put(key, value); - } - } - -} +package ecologylab.generic; + +import java.util.Map; + +/** + * Hashed data structure with synchronized writes/deletes and unsynchronized reads. + * + * @author andruid, robinson + * + * @param + * @param + */ +public class HashMapWriteSynch extends HashMapWriteSynchBase +{ + final ValueFactory factory; + + public HashMapWriteSynch(ValueFactory factory, int arg0, float arg1) + { + super(arg0, arg1); + this.factory = factory; + } + + public HashMapWriteSynch(ValueFactory factory, int arg0) + { + super(arg0); + this.factory = factory; + } + + public HashMapWriteSynch(ValueFactory factory) + { + super(); + this.factory = factory; + } + + public HashMapWriteSynch(ValueFactory factory, Map arg0) + { + super(arg0); + this.factory = factory; + } + + /** + * If there is already an entry, return it. + * + * Otherwise, create an entry with the factory. + * + * @return The entry matching key, found or constructed. + */ + public V getOrConstruct(K key) + { + V result = get(key); + if (result == null) + { + synchronized (this) + { + result = get(key); + if (result == null) + { + result = factory.constructValue(key); + super.put(key, result); + } + } + } + return result; + } + + + @Override + public V put(K key, V value) + { + synchronized(this) + { + return super.put(key, value); + } + } + +} diff --git a/simplCore/src/ecologylab/generic/HashMapWriteSynch2Args.java b/simplCore/src/ecologylab/generic/HashMapWriteSynch2Args.java index 3200f497..a2d79e61 100644 --- a/simplCore/src/ecologylab/generic/HashMapWriteSynch2Args.java +++ b/simplCore/src/ecologylab/generic/HashMapWriteSynch2Args.java @@ -1,107 +1,107 @@ -/** - * - */ -package ecologylab.generic; - -import java.util.Map; - -/** - * Hashed data structure with synchronized writes/deletes and unsynchronized reads. - * Constructor takes 2 args. First one is the key. - * - * @author andruid, robinson - * - * @param - * @param - * @param 2nd argument to value constructor - */ -public class HashMapWriteSynch2Args extends HashMapWriteSynchBase -{ - ValueFactory2 factory; - - /** - * @param arg0 - * @param arg1 - */ - public HashMapWriteSynch2Args(int arg0, float arg1) - { - super(arg0, arg1); - // TODO Auto-generated constructor stub - } - - /** - * @param arg0 number of elements allocated for initially. - */ - public HashMapWriteSynch2Args(int arg0) - { - super(arg0); - } - - /** - * - * @param arg0 number of elements allocated for initially. - * - * @param factory - */ - public HashMapWriteSynch2Args(int arg0, ValueFactory2 factory) - { - super(arg0); - this.factory = factory; - } - - /** - * - */ - public HashMapWriteSynch2Args() - { - // TODO Auto-generated constructor stub - } - - /** - * @param arg0 - */ - public HashMapWriteSynch2Args(Map arg0) - { - super(arg0); - // TODO Auto-generated constructor stub - } - - /** - * If there is already an entry, return it. - * - * Otherwise, create an entry with the factory. - * - * @return The entry matching key, found or constructed. - */ - public V getOrCreateAndPutIfNew(K key, A arg) - { - V result = get(key); - if (result == null) - { - synchronized (this) - { - result = get(key); - if (result == null) - { - result = this.factory.createValue(key, arg); - super.put(key, result); - } - } - } - return result; - } - - public ValueFactory2 getFactory() - { - return factory; - } - - /** - * @param factory the factory to set - */ - public void setFactory(ValueFactory2 factory) - { - this.factory = factory; - } - -} +/** + * + */ +package ecologylab.generic; + +import java.util.Map; + +/** + * Hashed data structure with synchronized writes/deletes and unsynchronized reads. + * Constructor takes 2 args. First one is the key. + * + * @author andruid, robinson + * + * @param + * @param + * @param 2nd argument to value constructor + */ +public class HashMapWriteSynch2Args extends HashMapWriteSynchBase +{ + ValueFactory2 factory; + + /** + * @param arg0 + * @param arg1 + */ + public HashMapWriteSynch2Args(int arg0, float arg1) + { + super(arg0, arg1); + // TODO Auto-generated constructor stub + } + + /** + * @param arg0 number of elements allocated for initially. + */ + public HashMapWriteSynch2Args(int arg0) + { + super(arg0); + } + + /** + * + * @param arg0 number of elements allocated for initially. + * + * @param factory + */ + public HashMapWriteSynch2Args(int arg0, ValueFactory2 factory) + { + super(arg0); + this.factory = factory; + } + + /** + * + */ + public HashMapWriteSynch2Args() + { + // TODO Auto-generated constructor stub + } + + /** + * @param arg0 + */ + public HashMapWriteSynch2Args(Map arg0) + { + super(arg0); + // TODO Auto-generated constructor stub + } + + /** + * If there is already an entry, return it. + * + * Otherwise, create an entry with the factory. + * + * @return The entry matching key, found or constructed. + */ + public V getOrCreateAndPutIfNew(K key, A arg) + { + V result = get(key); + if (result == null) + { + synchronized (this) + { + result = get(key); + if (result == null) + { + result = this.factory.createValue(key, arg); + super.put(key, result); + } + } + } + return result; + } + + public ValueFactory2 getFactory() + { + return factory; + } + + /** + * @param factory the factory to set + */ + public void setFactory(ValueFactory2 factory) + { + this.factory = factory; + } + +} diff --git a/simplCore/src/ecologylab/generic/HashMapWriteSynchBase.java b/simplCore/src/ecologylab/generic/HashMapWriteSynchBase.java index 6ec009ce..b6a4fdce 100644 --- a/simplCore/src/ecologylab/generic/HashMapWriteSynchBase.java +++ b/simplCore/src/ecologylab/generic/HashMapWriteSynchBase.java @@ -1,88 +1,88 @@ -/** - * - */ -package ecologylab.generic; - -import java.util.HashMap; -import java.util.Map; - -/** - * A HashMap that is synchronized for writes, but not for reads. - * - * @param Key type of the HashMap. - * @param Value type of the HashMap. - * - * @author andruid - */ -public class HashMapWriteSynchBase extends HashMap -{ - - public HashMapWriteSynchBase(int size, float load) - { - super(size, load); - } - - public HashMapWriteSynchBase(int size) - { - super(size); - } - - public HashMapWriteSynchBase() - { - super(); - } - - public HashMapWriteSynchBase(Map arg0) - { - super(arg0); - } - - /** - * If there is already an entry, return it. - * - * Otherwise, add the entry, and return null. - *

- * NB: NEVER replaces an existing entry. - */ - public V getOrPutIfNew(K key, V value) - { - V result = get(key); - if (result == null) - { - synchronized (this) - { - result = get(key); - if (result == null) - { - result = super.put(key, value); - } - } - } - return result; - } - - /** - * Sycnhronizes remove. - */ - @Override - public synchronized V remove(Object key) - { - return super.remove(key); - } - - /** - * Sycnhronizes if you add another map to this one. - */ - @Override - public synchronized void putAll(Map m) - { - super.putAll(m); - } -/* - @Override - public V put(K key, V value) - { - throw new RuntimeException("Don't call plain put on this class!!! Bad synch mojo."); - } - */ -} +/** + * + */ +package ecologylab.generic; + +import java.util.HashMap; +import java.util.Map; + +/** + * A HashMap that is synchronized for writes, but not for reads. + * + * @param Key type of the HashMap. + * @param Value type of the HashMap. + * + * @author andruid + */ +public class HashMapWriteSynchBase extends HashMap +{ + + public HashMapWriteSynchBase(int size, float load) + { + super(size, load); + } + + public HashMapWriteSynchBase(int size) + { + super(size); + } + + public HashMapWriteSynchBase() + { + super(); + } + + public HashMapWriteSynchBase(Map arg0) + { + super(arg0); + } + + /** + * If there is already an entry, return it. + * + * Otherwise, add the entry, and return null. + *

+ * NB: NEVER replaces an existing entry. + */ + public V getOrPutIfNew(K key, V value) + { + V result = get(key); + if (result == null) + { + synchronized (this) + { + result = get(key); + if (result == null) + { + result = super.put(key, value); + } + } + } + return result; + } + + /** + * Sycnhronizes remove. + */ + @Override + public synchronized V remove(Object key) + { + return super.remove(key); + } + + /** + * Sycnhronizes if you add another map to this one. + */ + @Override + public synchronized void putAll(Map m) + { + super.putAll(m); + } +/* + @Override + public V put(K key, V value) + { + throw new RuntimeException("Don't call plain put on this class!!! Bad synch mojo."); + } + */ +} diff --git a/simplCore/src/ecologylab/generic/HashMappableArrayList.java b/simplCore/src/ecologylab/generic/HashMappableArrayList.java index cc6d752d..1d4d0dc9 100644 --- a/simplCore/src/ecologylab/generic/HashMappableArrayList.java +++ b/simplCore/src/ecologylab/generic/HashMappableArrayList.java @@ -1,126 +1,126 @@ -/** - * - */ -package ecologylab.generic; - -import java.util.Collection; -import java.util.Map; - -import ecologylab.serialization.types.element.IMappable; - -/** - * A HashMap with an ArrayList backing store, for speedy linear and hashed access. - * Each Value also implements Mappable, and so functions as a key. - * This means that we can implement Collection, because it guides us, for example, - * in performing a hashed put() when a linear add() is called. - * - * @author andruid - * @param - */ -public class HashMappableArrayList> extends HashMapArrayList -//implements Collection -{ - - /** - * - */ - public HashMappableArrayList() - {} - - /** - * @param arg0 - */ - public HashMappableArrayList(int arg0) - { - super(arg0); - - } - - /** - * @param arg0 - */ - public HashMappableArrayList(Map arg0) - { - super(arg0); - - } - - /** - * @param arg0 - * @param arg1 - */ - public HashMappableArrayList(int arg0, float arg1) - { - super(arg0, arg1); - - } - - /** - * Add element to HashMap and to ArrayList, unless same element was already in HashMap. - * - * @param v - * @return - */ - public boolean add(V v) - { - V fromMap = put(v.key(), v); - boolean mapChanged = fromMap != v; - if (mapChanged) - { // map changed - new element added - if (fromMap != null) - { // old element must be removed - arrayList.remove(fromMap); - } - arrayList.add(v); - } - return mapChanged; - } - - public boolean addAll(Collection collection) - { - boolean result = false; - for (Object o : collection) - { - if (o != null) - { - V value = (V) o; - result |= this.add(value); - } - } - return result; - } - - public boolean contains(V v) - { - return super.containsKey(v.key()); - } - - public boolean containsAll(Collection c) - { - // TODO Auto-generated method stub - return false; - } - - public boolean removeAll(Collection c) - { - // TODO Auto-generated method stub - return false; - } - - public boolean retainAll(Collection c) - { - // TODO Auto-generated method stub - return false; - } - - public Object[] toArray() - { - return this.arrayList.toArray(); - } - - public Object[] toArray(Object[] a) - { - return this.arrayList.toArray(a); - } - -} +/** + * + */ +package ecologylab.generic; + +import java.util.Collection; +import java.util.Map; + +import ecologylab.serialization.types.element.IMappable; + +/** + * A HashMap with an ArrayList backing store, for speedy linear and hashed access. + * Each Value also implements Mappable, and so functions as a key. + * This means that we can implement Collection, because it guides us, for example, + * in performing a hashed put() when a linear add() is called. + * + * @author andruid + * @param + */ +public class HashMappableArrayList> extends HashMapArrayList +//implements Collection +{ + + /** + * + */ + public HashMappableArrayList() + {} + + /** + * @param arg0 + */ + public HashMappableArrayList(int arg0) + { + super(arg0); + + } + + /** + * @param arg0 + */ + public HashMappableArrayList(Map arg0) + { + super(arg0); + + } + + /** + * @param arg0 + * @param arg1 + */ + public HashMappableArrayList(int arg0, float arg1) + { + super(arg0, arg1); + + } + + /** + * Add element to HashMap and to ArrayList, unless same element was already in HashMap. + * + * @param v + * @return + */ + public boolean add(V v) + { + V fromMap = put(v.key(), v); + boolean mapChanged = fromMap != v; + if (mapChanged) + { // map changed - new element added + if (fromMap != null) + { // old element must be removed + arrayList.remove(fromMap); + } + arrayList.add(v); + } + return mapChanged; + } + + public boolean addAll(Collection collection) + { + boolean result = false; + for (Object o : collection) + { + if (o != null) + { + V value = (V) o; + result |= this.add(value); + } + } + return result; + } + + public boolean contains(V v) + { + return super.containsKey(v.key()); + } + + public boolean containsAll(Collection c) + { + // TODO Auto-generated method stub + return false; + } + + public boolean removeAll(Collection c) + { + // TODO Auto-generated method stub + return false; + } + + public boolean retainAll(Collection c) + { + // TODO Auto-generated method stub + return false; + } + + public Object[] toArray() + { + return this.arrayList.toArray(); + } + + public Object[] toArray(Object[] a) + { + return this.arrayList.toArray(a); + } + +} diff --git a/simplCore/src/ecologylab/generic/HashSetWriteSynch.java b/simplCore/src/ecologylab/generic/HashSetWriteSynch.java index f8799e58..66d72cf6 100644 --- a/simplCore/src/ecologylab/generic/HashSetWriteSynch.java +++ b/simplCore/src/ecologylab/generic/HashSetWriteSynch.java @@ -1,65 +1,65 @@ -package ecologylab.generic; - -import java.util.Collection; -import java.util.HashSet; - -/** - * Hashed data structure with synchronized writes/deletes and unsynchronized reads. - * - * @author andruid, robinson - * - * @param - * @param - */ -public class HashSetWriteSynch extends HashSet -{ - - public HashSetWriteSynch(int arg0, float arg1) - { - super(arg0, arg1); - } - - public HashSetWriteSynch(int arg0) - { - super(arg0); - } - - public HashSetWriteSynch() - { - super(); - } - - - public HashSetWriteSynch(Collection collection) - { - super(collection); - } - - - /** - * Sycnhronizes add. - */ - @Override - public synchronized boolean add(K key) - { - return super.add(key); - } - - /** - * Sycnhronizes remove. - */ - @Override - public synchronized boolean remove(Object key) - { - return super.remove(key); - } - - /** - * Sycnhronizes if you add another set to this one. - */ - @Override - public synchronized boolean addAll(Collection c) - { - return super.addAll(c); - } -} +package ecologylab.generic; + +import java.util.Collection; +import java.util.HashSet; + +/** + * Hashed data structure with synchronized writes/deletes and unsynchronized reads. + * + * @author andruid, robinson + * + * @param + * @param + */ +public class HashSetWriteSynch extends HashSet +{ + + public HashSetWriteSynch(int arg0, float arg1) + { + super(arg0, arg1); + } + + public HashSetWriteSynch(int arg0) + { + super(arg0); + } + + public HashSetWriteSynch() + { + super(); + } + + + public HashSetWriteSynch(Collection collection) + { + super(collection); + } + + + /** + * Sycnhronizes add. + */ + @Override + public synchronized boolean add(K key) + { + return super.add(key); + } + + /** + * Sycnhronizes remove. + */ + @Override + public synchronized boolean remove(Object key) + { + return super.remove(key); + } + + /** + * Sycnhronizes if you add another set to this one. + */ + @Override + public synchronized boolean addAll(Collection c) + { + return super.addAll(c); + } +} diff --git a/simplCore/src/ecologylab/generic/IFeatureVector.java b/simplCore/src/ecologylab/generic/IFeatureVector.java index 2412fba3..49b66c1e 100644 --- a/simplCore/src/ecologylab/generic/IFeatureVector.java +++ b/simplCore/src/ecologylab/generic/IFeatureVector.java @@ -1,110 +1,110 @@ -package ecologylab.generic; - -import java.util.Map; -import java.util.Set; - -import ecologylab.pools.HashMapPool; - -public interface IFeatureVector -{ - public static final HashMapPool HASH_MAP_POOL = new HashMapPool(128, 20); - - /** - * - * @param term - * @return - */ - public double get ( T term ); - - /** - * Calculates the dot product of this vector with another vector. - * - * @param v - * Vector to dot this Vector with. - */ - public double dot ( IFeatureVector v ); - - /** - * Calculates the Euclidean norm/length of this vector. The squares of each element are added - * together, and the square root of the result is taken and returned. - * - * @return The norm of the vector - */ - public double norm ( ); - - /** - * Returns the value in the vector with the largest magnitude. - * ( e.g. -5 is the max of {0,2,4,-5} ) - * @return the max value in the vector - */ - public double max ( ); - - /** - * The set of elements which have some value associated with them in this FeatureVector.
- * By convention, this set is not backed by the FeatureVector so it may be modified without - * consequence.
- *
- * - * Other implementations should try to follow this convention as well. - * - * @return the set of elements represented in this FeatureVector. - */ - public Set elements ( ); - - /** - * The set of values which have some element associated with them in this FeatureVector.
- * By convention, this set is not backed by the FeatureVector so it may be modified without - * consequence.
- *
- * - * Other implementations should try to follow this convention as well. - * - * @return the set of values represented in this FeatureVector. - */ - public Set values ( ); - - /** - * A reference to the underlying Map backing this vector - * - * @return the Map representing a particular FeatureVector - */ - public Map map ( ); - - /** - * Creates a new vector equivalent to this.clamp(1). Not a real unit vector in - * the euclidean sense. - * - * @return unit length FeatureVector - */ - public IFeatureVector unit ( ); - - /** - * Creates a new vector with the same elements as this vector, setting all the values to 1. - * - * @return simplex FeatureVector - */ - public IFeatureVector simplex ( ); - - /** - * Returns the dot product of this vector and the simplex of the passed in vector.
- *
- * - * You can the average value of all the elements in this vector which are common to - * both by dividing this result by the commonDimensions. - * - * @param v - * vector to simplex and dot with this vector - * @return - */ - public double dotSimplex ( IFeatureVector v ); - - /** - * Returns the number of common elements in this vector and the passed in vector - * - * @param v - * @return - */ - public int commonDimensions ( IFeatureVector v ); - - public boolean isRecycled(); +package ecologylab.generic; + +import java.util.Map; +import java.util.Set; + +import ecologylab.pools.HashMapPool; + +public interface IFeatureVector +{ + public static final HashMapPool HASH_MAP_POOL = new HashMapPool(128, 20); + + /** + * + * @param term + * @return + */ + public double get ( T term ); + + /** + * Calculates the dot product of this vector with another vector. + * + * @param v + * Vector to dot this Vector with. + */ + public double dot ( IFeatureVector v ); + + /** + * Calculates the Euclidean norm/length of this vector. The squares of each element are added + * together, and the square root of the result is taken and returned. + * + * @return The norm of the vector + */ + public double norm ( ); + + /** + * Returns the value in the vector with the largest magnitude. + * ( e.g. -5 is the max of {0,2,4,-5} ) + * @return the max value in the vector + */ + public double max ( ); + + /** + * The set of elements which have some value associated with them in this FeatureVector.
+ * By convention, this set is not backed by the FeatureVector so it may be modified without + * consequence.
+ *
+ * + * Other implementations should try to follow this convention as well. + * + * @return the set of elements represented in this FeatureVector. + */ + public Set elements ( ); + + /** + * The set of values which have some element associated with them in this FeatureVector.
+ * By convention, this set is not backed by the FeatureVector so it may be modified without + * consequence.
+ *
+ * + * Other implementations should try to follow this convention as well. + * + * @return the set of values represented in this FeatureVector. + */ + public Set values ( ); + + /** + * A reference to the underlying Map backing this vector + * + * @return the Map representing a particular FeatureVector + */ + public Map map ( ); + + /** + * Creates a new vector equivalent to this.clamp(1). Not a real unit vector in + * the euclidean sense. + * + * @return unit length FeatureVector + */ + public IFeatureVector unit ( ); + + /** + * Creates a new vector with the same elements as this vector, setting all the values to 1. + * + * @return simplex FeatureVector + */ + public IFeatureVector simplex ( ); + + /** + * Returns the dot product of this vector and the simplex of the passed in vector.
+ *
+ * + * You can the average value of all the elements in this vector which are common to + * both by dividing this result by the commonDimensions. + * + * @param v + * vector to simplex and dot with this vector + * @return + */ + public double dotSimplex ( IFeatureVector v ); + + /** + * Returns the number of common elements in this vector and the passed in vector + * + * @param v + * @return + */ + public int commonDimensions ( IFeatureVector v ); + + public boolean isRecycled(); } \ No newline at end of file diff --git a/simplCore/src/ecologylab/generic/ImageTools.java b/simplCore/src/ecologylab/generic/ImageTools.java index 93bb1f6a..6746d486 100644 --- a/simplCore/src/ecologylab/generic/ImageTools.java +++ b/simplCore/src/ecologylab/generic/ImageTools.java @@ -1,383 +1,383 @@ -package ecologylab.generic; - -import java.awt.AlphaComposite; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.awt.image.RenderedImage; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Iterator; -import java.util.Locale; - -import javax.imageio.IIOImage; -import javax.imageio.ImageIO; -import javax.imageio.ImageWriteParam; -import javax.imageio.ImageWriter; -import javax.imageio.plugins.jpeg.JPEGImageWriteParam; -import javax.imageio.stream.ImageOutputStream; - -/** - * A set of lovely convenience methods for working with images. - */ -public class ImageTools extends Debug -{ - - /** - * Returns the new rectangle, which is the bounding box for rect rotated by - * theta around the center - * - * @param rect - * @param theta - * @return - */ - public static Rectangle getRotatedExtent(Rectangle rect, double theta) - { - return getRotatedExtent(rect.width, rect.height, theta); - } - - /** - * Calculates the new bounding box for a rectangle with width, height rotated by an angle theta - * around the center - * - * @param width - * @param height - * @param theta - * @return - */ - public static Rectangle getRotatedExtent(int width, int height, double theta) - { - double diag = Math.sqrt(width * width + height * height); - double alpha = Math.atan2(height, width); - double newWidth = diag * Math.cos(theta - alpha); - double newHeight = diag * Math.cos(Math.PI / 2 - theta - alpha); - return new Rectangle((int) newWidth, (int) newHeight); - } - - /** - * Make a copy of the BufferedImage. - * - * @param srcImage - * @param destImage - */ - public static void copyImage(BufferedImage srcImage, BufferedImage destImage) - { - // scaleAndCopyImage(srcImage.getWidth(), srcImage.getHeight(), srcImage, destImage); - Graphics2D g2 = destImage.createGraphics(); - g2.setComposite(AlphaComposite.Src); - g2.drawImage(srcImage, 0, 0, null); - g2.dispose(); - } - - /** - * Make a scaled copy of the BufferedImage. Uses INTERPOLATION_BILINEAR. - * - * @param srcImage - * @param destImage - */ - public static void scaleAndCopyImage(int newWidth, int newHeight, BufferedImage srcImage, - BufferedImage destImage) - { - // AffineTransformOp scaleOp = createScaleOp(newWidth, newHeight, width, height); - // scaleOp.filter(bufferedImage, scaledBImage); - // faster than using AffineTransformOp scaleOp. i promise. - // -- use the source, luke! - - Graphics2D g2 = destImage.createGraphics(); - g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR); - g2.drawImage(srcImage, 0, 0, newWidth, newHeight, null); - g2.dispose(); - } - - /** - * Take the RenderedImage passed in, compress it, and writes it to a file created from - * outfileName. - * - * @param compressionQuality - * ranges between 0 and 1, 0-lowest, 1-highest. - */ - public static void writeJpegFile(RenderedImage rendImage, String outfileName, - float compressionQuality) - { - writeJpegFile(rendImage, new File(outfileName), compressionQuality); - } - - public static void writeFile(RenderedImage rendImage, File outfile, String formatName) - { - writeToTarget(rendImage, outfile, outfile.getName(), formatName); - } - - private static void writeToTarget(RenderedImage rendImage, Object outputTarget, String targetName, String formatName) - { - if (rendImage == null) - { - error(ImageTools.class, "rendered image is NULL! cannot save image file."); - return; - } - - try - { - // Find a png writer - ImageWriter writer = null; - Iterator iter = ImageIO.getImageWritersByFormatName(formatName); - if (iter.hasNext()) - { - writer = (ImageWriter) iter.next(); - } - else - { - Debug.error(rendImage, "no image writer for " + targetName); - return; - } - - // Prepare output file - ImageOutputStream ios = ImageIO.createImageOutputStream(outputTarget); - writer.setOutput(ios); - - ImageTools imageTools = new ImageTools(); - // Set the compression quality - ImageWriteParam iwparam = imageTools.new MyImageWriteParam(); - - // Write the image - writer.write(null, new IIOImage(rendImage, null, null), iwparam); - - // Cleanup - ios.flush(); - writer.dispose(); - ios.close(); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - public static void writePngFile(RenderedImage rendImage, File outfile) - { - writeFile(rendImage, outfile, "png"); - } - - public static void writePngStream(RenderedImage rendImage, OutputStream outStream) - { - writeToTarget(rendImage, outStream, outStream.toString(), "png"); - } - - public static void writeTifFile(RenderedImage rendImage, File outfile) - { - writeFile(rendImage, outfile, "tif"); - } - - /** - * Take the RenderedImage passed in, compress it, and writes it to outfile. - * - * @param compressionQuality - * ranges between 0 and 1, 0-lowest, 1-highest. - */ - public static void writeJpegFile(RenderedImage rendImage, File outfile, float compressionQuality) - { - writeJpegToTarget(rendImage, outfile, compressionQuality); - } - - public static void writeJpegStream(RenderedImage rendImage, OutputStream outStream, float compressionQuality) - { - writeJpegToTarget(rendImage, outStream, compressionQuality); - } - - private static void writeJpegToTarget(RenderedImage rendImage, Object target, - float compressionQuality) - { - try - { - // Find a jpeg writer - ImageWriter writer = null; - Iterator iter = ImageIO.getImageWritersByFormatName("jpg"); - if (iter.hasNext()) - { - writer = (ImageWriter) iter.next(); - } - // Prepare output file - ImageOutputStream ios = ImageIO.createImageOutputStream(target); - writer.setOutput(ios); - - ImageTools imageTools = new ImageTools(); - // Set the compression quality - ImageWriteParam iwparam = imageTools.new MyImageWriteParam(); - iwparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); - iwparam.setCompressionQuality(compressionQuality); - - // Write the image - writer.write(null, new IIOImage(rendImage, null, null), iwparam); - - // Cleanup - ios.flush(); - writer.dispose(); - ios.close(); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - /** - * Scale the image, then write a jpeg. - */ - /** - * Take the RenderedImage passed in, compress it, and writes it to a file created from - * outfileName. - * - * @param compressionQuality - * ranges between 0 and 1, 0-lowest, 1-highest. - */ - public static void writeJpegFile(BufferedImage image, String fileName, float compressionQuality, - int width, int height) - { - BufferedImage scaledImage = scaleJpeg(image, width, height); - writeJpegFile(scaledImage, fileName, compressionQuality); - } - - public static void writeJpegStream(BufferedImage image, OutputStream outStream, float compressionQuality, - int width, int height) - { - BufferedImage scaledImage = scaleJpeg(image, width, height); - writeJpegStream(scaledImage, outStream, compressionQuality); - } - - private static BufferedImage scaleJpeg(BufferedImage image, int width, int height) - { - // final int THUMBNAIL_WIDTH = 245; - // final int THUMBNAIL_HEIGHT = 350; - - // int width = THUMBNAIL_WIDTH; - // int height = THUMBNAIL_HEIGHT; - - float thumbRatio = (float) width / (float) height; - int imageWidth = image.getWidth(null); - int imageHeight = image.getHeight(null); - float imageRatio = (float) imageWidth / (float) imageHeight; - - if (thumbRatio < imageRatio) - { - height = (int) (width / imageRatio); - } - else - { - width = (int) (height * imageRatio); - } - // println("writeThumbnail("+width+","+height+ - // " type="+image.getType()); - - // draw original image to thumbnail image object and - // scale it to the new size on-the-fly - BufferedImage scaledImage = new BufferedImage(width, height, image.getType()); - - Graphics2D graphics2D = scaledImage.createGraphics(); - - graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR); - - graphics2D.drawImage(image, 0, 0, width, height, null); - return scaledImage; - } - - // This class overrides the setCompressionQuality() method to workaround - // a problem in compressing JPEG images using the javax.imageio package. - class MyImageWriteParam extends JPEGImageWriteParam - { - public MyImageWriteParam() - { - super(Locale.getDefault()); - } - - // This method accepts quality levels between 0 (lowest) and 1 (highest) and simply converts - // it to a range between 0 and 256; this is not a correct conversion algorithm. - // However, a proper alternative is a lot more complicated. - // This should do until the bug is fixed. - @Override - public void setCompressionQuality(float quality) - { - if (quality < 0.0F || quality > 1.0F) - { - throw new IllegalArgumentException("Quality out-of-bounds!"); - } - this.compressionQuality = 256 - (quality * 256); - } - } - - /** - * Borrowed code from : http://forums.sun.com/thread.jspa?threadID=524460 - * Allows determining the byte size of a compressed image. - * - * @param image - * @param quality - * @param out - * @throws IOException - */ - public static void write(BufferedImage image, float quality, OutputStream out) throws IOException - { - Iterator writers = ImageIO.getImageWritersBySuffix("jpeg"); - if (!writers.hasNext()) - throw new IllegalStateException("No writers found"); - ImageWriter writer = (ImageWriter) writers.next(); - ImageOutputStream ios = ImageIO.createImageOutputStream(out); - writer.setOutput(ios); - ImageWriteParam param = writer.getDefaultWriteParam(); - if (quality >= 0) - { - param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); - param.setCompressionQuality(quality); - } - writer.write(null, new IIOImage(image, null, null), param); - } - - /** - * Uses image quality of .5 - * @param image - * @return - */ - public static int getNumBytes(BufferedImage image) - { - return getNumBytes(image, .5f); - } - - /** - * Altered method to NOT create a byteArray to find size. - * @param image - * @param quality - * @return - */ - public static int getNumBytes(BufferedImage image, float quality) - { - try - { - ByteArrayOutputStream out = new ByteArrayOutputStream(5000); - write(image, quality, out); - return out.size(); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - - - public static byte[] getBytes(BufferedImage image, float quality) - { - try - { - ByteArrayOutputStream out = new ByteArrayOutputStream(5000); - write(image, quality, out); - return out.toByteArray(); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - - -} +package ecologylab.generic; + +import java.awt.AlphaComposite; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.awt.image.RenderedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.Locale; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.plugins.jpeg.JPEGImageWriteParam; +import javax.imageio.stream.ImageOutputStream; + +/** + * A set of lovely convenience methods for working with images. + */ +public class ImageTools extends Debug +{ + + /** + * Returns the new rectangle, which is the bounding box for rect rotated by + * theta around the center + * + * @param rect + * @param theta + * @return + */ + public static Rectangle getRotatedExtent(Rectangle rect, double theta) + { + return getRotatedExtent(rect.width, rect.height, theta); + } + + /** + * Calculates the new bounding box for a rectangle with width, height rotated by an angle theta + * around the center + * + * @param width + * @param height + * @param theta + * @return + */ + public static Rectangle getRotatedExtent(int width, int height, double theta) + { + double diag = Math.sqrt(width * width + height * height); + double alpha = Math.atan2(height, width); + double newWidth = diag * Math.cos(theta - alpha); + double newHeight = diag * Math.cos(Math.PI / 2 - theta - alpha); + return new Rectangle((int) newWidth, (int) newHeight); + } + + /** + * Make a copy of the BufferedImage. + * + * @param srcImage + * @param destImage + */ + public static void copyImage(BufferedImage srcImage, BufferedImage destImage) + { + // scaleAndCopyImage(srcImage.getWidth(), srcImage.getHeight(), srcImage, destImage); + Graphics2D g2 = destImage.createGraphics(); + g2.setComposite(AlphaComposite.Src); + g2.drawImage(srcImage, 0, 0, null); + g2.dispose(); + } + + /** + * Make a scaled copy of the BufferedImage. Uses INTERPOLATION_BILINEAR. + * + * @param srcImage + * @param destImage + */ + public static void scaleAndCopyImage(int newWidth, int newHeight, BufferedImage srcImage, + BufferedImage destImage) + { + // AffineTransformOp scaleOp = createScaleOp(newWidth, newHeight, width, height); + // scaleOp.filter(bufferedImage, scaledBImage); + // faster than using AffineTransformOp scaleOp. i promise. + // -- use the source, luke! + + Graphics2D g2 = destImage.createGraphics(); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g2.drawImage(srcImage, 0, 0, newWidth, newHeight, null); + g2.dispose(); + } + + /** + * Take the RenderedImage passed in, compress it, and writes it to a file created from + * outfileName. + * + * @param compressionQuality + * ranges between 0 and 1, 0-lowest, 1-highest. + */ + public static void writeJpegFile(RenderedImage rendImage, String outfileName, + float compressionQuality) + { + writeJpegFile(rendImage, new File(outfileName), compressionQuality); + } + + public static void writeFile(RenderedImage rendImage, File outfile, String formatName) + { + writeToTarget(rendImage, outfile, outfile.getName(), formatName); + } + + private static void writeToTarget(RenderedImage rendImage, Object outputTarget, String targetName, String formatName) + { + if (rendImage == null) + { + error(ImageTools.class, "rendered image is NULL! cannot save image file."); + return; + } + + try + { + // Find a png writer + ImageWriter writer = null; + Iterator iter = ImageIO.getImageWritersByFormatName(formatName); + if (iter.hasNext()) + { + writer = (ImageWriter) iter.next(); + } + else + { + Debug.error(rendImage, "no image writer for " + targetName); + return; + } + + // Prepare output file + ImageOutputStream ios = ImageIO.createImageOutputStream(outputTarget); + writer.setOutput(ios); + + ImageTools imageTools = new ImageTools(); + // Set the compression quality + ImageWriteParam iwparam = imageTools.new MyImageWriteParam(); + + // Write the image + writer.write(null, new IIOImage(rendImage, null, null), iwparam); + + // Cleanup + ios.flush(); + writer.dispose(); + ios.close(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + public static void writePngFile(RenderedImage rendImage, File outfile) + { + writeFile(rendImage, outfile, "png"); + } + + public static void writePngStream(RenderedImage rendImage, OutputStream outStream) + { + writeToTarget(rendImage, outStream, outStream.toString(), "png"); + } + + public static void writeTifFile(RenderedImage rendImage, File outfile) + { + writeFile(rendImage, outfile, "tif"); + } + + /** + * Take the RenderedImage passed in, compress it, and writes it to outfile. + * + * @param compressionQuality + * ranges between 0 and 1, 0-lowest, 1-highest. + */ + public static void writeJpegFile(RenderedImage rendImage, File outfile, float compressionQuality) + { + writeJpegToTarget(rendImage, outfile, compressionQuality); + } + + public static void writeJpegStream(RenderedImage rendImage, OutputStream outStream, float compressionQuality) + { + writeJpegToTarget(rendImage, outStream, compressionQuality); + } + + private static void writeJpegToTarget(RenderedImage rendImage, Object target, + float compressionQuality) + { + try + { + // Find a jpeg writer + ImageWriter writer = null; + Iterator iter = ImageIO.getImageWritersByFormatName("jpg"); + if (iter.hasNext()) + { + writer = (ImageWriter) iter.next(); + } + // Prepare output file + ImageOutputStream ios = ImageIO.createImageOutputStream(target); + writer.setOutput(ios); + + ImageTools imageTools = new ImageTools(); + // Set the compression quality + ImageWriteParam iwparam = imageTools.new MyImageWriteParam(); + iwparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + iwparam.setCompressionQuality(compressionQuality); + + // Write the image + writer.write(null, new IIOImage(rendImage, null, null), iwparam); + + // Cleanup + ios.flush(); + writer.dispose(); + ios.close(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * Scale the image, then write a jpeg. + */ + /** + * Take the RenderedImage passed in, compress it, and writes it to a file created from + * outfileName. + * + * @param compressionQuality + * ranges between 0 and 1, 0-lowest, 1-highest. + */ + public static void writeJpegFile(BufferedImage image, String fileName, float compressionQuality, + int width, int height) + { + BufferedImage scaledImage = scaleJpeg(image, width, height); + writeJpegFile(scaledImage, fileName, compressionQuality); + } + + public static void writeJpegStream(BufferedImage image, OutputStream outStream, float compressionQuality, + int width, int height) + { + BufferedImage scaledImage = scaleJpeg(image, width, height); + writeJpegStream(scaledImage, outStream, compressionQuality); + } + + private static BufferedImage scaleJpeg(BufferedImage image, int width, int height) + { + // final int THUMBNAIL_WIDTH = 245; + // final int THUMBNAIL_HEIGHT = 350; + + // int width = THUMBNAIL_WIDTH; + // int height = THUMBNAIL_HEIGHT; + + float thumbRatio = (float) width / (float) height; + int imageWidth = image.getWidth(null); + int imageHeight = image.getHeight(null); + float imageRatio = (float) imageWidth / (float) imageHeight; + + if (thumbRatio < imageRatio) + { + height = (int) (width / imageRatio); + } + else + { + width = (int) (height * imageRatio); + } + // println("writeThumbnail("+width+","+height+ + // " type="+image.getType()); + + // draw original image to thumbnail image object and + // scale it to the new size on-the-fly + BufferedImage scaledImage = new BufferedImage(width, height, image.getType()); + + Graphics2D graphics2D = scaledImage.createGraphics(); + + graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); + + graphics2D.drawImage(image, 0, 0, width, height, null); + return scaledImage; + } + + // This class overrides the setCompressionQuality() method to workaround + // a problem in compressing JPEG images using the javax.imageio package. + class MyImageWriteParam extends JPEGImageWriteParam + { + public MyImageWriteParam() + { + super(Locale.getDefault()); + } + + // This method accepts quality levels between 0 (lowest) and 1 (highest) and simply converts + // it to a range between 0 and 256; this is not a correct conversion algorithm. + // However, a proper alternative is a lot more complicated. + // This should do until the bug is fixed. + @Override + public void setCompressionQuality(float quality) + { + if (quality < 0.0F || quality > 1.0F) + { + throw new IllegalArgumentException("Quality out-of-bounds!"); + } + this.compressionQuality = 256 - (quality * 256); + } + } + + /** + * Borrowed code from : http://forums.sun.com/thread.jspa?threadID=524460 + * Allows determining the byte size of a compressed image. + * + * @param image + * @param quality + * @param out + * @throws IOException + */ + public static void write(BufferedImage image, float quality, OutputStream out) throws IOException + { + Iterator writers = ImageIO.getImageWritersBySuffix("jpeg"); + if (!writers.hasNext()) + throw new IllegalStateException("No writers found"); + ImageWriter writer = (ImageWriter) writers.next(); + ImageOutputStream ios = ImageIO.createImageOutputStream(out); + writer.setOutput(ios); + ImageWriteParam param = writer.getDefaultWriteParam(); + if (quality >= 0) + { + param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param.setCompressionQuality(quality); + } + writer.write(null, new IIOImage(image, null, null), param); + } + + /** + * Uses image quality of .5 + * @param image + * @return + */ + public static int getNumBytes(BufferedImage image) + { + return getNumBytes(image, .5f); + } + + /** + * Altered method to NOT create a byteArray to find size. + * @param image + * @param quality + * @return + */ + public static int getNumBytes(BufferedImage image, float quality) + { + try + { + ByteArrayOutputStream out = new ByteArrayOutputStream(5000); + write(image, quality, out); + return out.size(); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + + public static byte[] getBytes(BufferedImage image, float quality) + { + try + { + ByteArrayOutputStream out = new ByteArrayOutputStream(5000); + write(image, quality, out); + return out.toByteArray(); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + +} diff --git a/simplCore/src/ecologylab/generic/IntSlot.java b/simplCore/src/ecologylab/generic/IntSlot.java index 7b83c767..8bd507d7 100644 --- a/simplCore/src/ecologylab/generic/IntSlot.java +++ b/simplCore/src/ecologylab/generic/IntSlot.java @@ -1,44 +1,44 @@ -// Copyright 1996 by Creating Media. All rights reserved. -package ecologylab.generic; - - -/** - * Reference version of an int type. Re-writable, unlike java.lang.Integer. - *

- * Object wrapper for int primitive values. - * Useful for storing in HashMaps, and anywhere else that a reference type is needed. - */ -public class IntSlot -extends Object -{ - public int value; - - public IntSlot(int b) - { - super(); - value = b; - } - /** - * - */ -public IntSlot() -{ - - // TODO Auto-generated constructor stub -} - /** - * Returns a hashcode for this Integer. - * - * @return a hash code value for this object. - * @since JDK1.0 - */ - @Override - public int hashCode() { - return value; - } - @Override -public String toString() - { - return "IntSlot[" + value + "]"; - } -} +// Copyright 1996 by Creating Media. All rights reserved. +package ecologylab.generic; + + +/** + * Reference version of an int type. Re-writable, unlike java.lang.Integer. + *

+ * Object wrapper for int primitive values. + * Useful for storing in HashMaps, and anywhere else that a reference type is needed. + */ +public class IntSlot +extends Object +{ + public int value; + + public IntSlot(int b) + { + super(); + value = b; + } + /** + * + */ +public IntSlot() +{ + + // TODO Auto-generated constructor stub +} + /** + * Returns a hashcode for this Integer. + * + * @return a hash code value for this object. + * @since JDK1.0 + */ + @Override + public int hashCode() { + return value; + } + @Override +public String toString() + { + return "IntSlot[" + value + "]"; + } +} diff --git a/simplCore/src/ecologylab/generic/ItemIndexPredicate.java b/simplCore/src/ecologylab/generic/ItemIndexPredicate.java index 438a9781..5869f5f2 100644 --- a/simplCore/src/ecologylab/generic/ItemIndexPredicate.java +++ b/simplCore/src/ecologylab/generic/ItemIndexPredicate.java @@ -1,22 +1,22 @@ -package ecologylab.generic; - -/** - * A predicate to describe indexing items for a multiindexer. - * @author tom - * - */ -public interface ItemIndexPredicate{ - - /** - * Gets the unique string used to identify items indexed by this predicate. - * @return - */ - String GetIndexIdentifier(); - /** - * OBtains a string index for a corresponding item. Items that are indexed in this manner will typically call some method on the indexed item to get a string. - * For example, indexing by a class name may require calling item.getClass().getName(). - * @param item - * @return - */ - String ObtainIndex(IndexedItem item); -} +package ecologylab.generic; + +/** + * A predicate to describe indexing items for a multiindexer. + * @author tom + * + */ +public interface ItemIndexPredicate{ + + /** + * Gets the unique string used to identify items indexed by this predicate. + * @return + */ + String GetIndexIdentifier(); + /** + * OBtains a string index for a corresponding item. Items that are indexed in this manner will typically call some method on the indexed item to get a string. + * For example, indexing by a class name may require calling item.getClass().getName(). + * @param item + * @return + */ + String ObtainIndex(IndexedItem item); +} diff --git a/simplCore/src/ecologylab/generic/Line2D.java b/simplCore/src/ecologylab/generic/Line2D.java index 3f4af62b..745fffda 100644 --- a/simplCore/src/ecologylab/generic/Line2D.java +++ b/simplCore/src/ecologylab/generic/Line2D.java @@ -1,46 +1,46 @@ -package ecologylab.generic; - -import java.awt.Graphics; - -/** - * A 2D line, as defined by parametric coefficients. - * The line, ultimately will be defined by 2 end points, that is, by 4 - * integers, when it is drawn. - * The parametric representation is of the form: - * x0 = a*x + b*width + c, - * y0 = a*y + b*height + c. - * - * Displacement1D holds these parametric forms. - * In our world a=1, always, so we assume that, and dont bother with - * the extra multiplication. (This could always be changed inside the - * encapsulated Displacement1D, without effecting the call sites.) - */ -public class Line2D -{ - Displacement1D x0, y0, x1, y1; - - public Line2D(int[] dx0, int[] dy0, int[] dx1, int[] dy1) - { - x0 = new Displacement1D(dx0); - } - public Line2D(int[] dx0) - { - x0 = new Displacement1D(dx0); - } - public Line2D(int dxb0, int dxc0, int dyb0, int dyc0, - int dxb1, int dxc1, int dyb1, int dyc1) - { - x0 = new Displacement1D(dxb0, dxc0); - y0 = new Displacement1D(dyb0, dyc0); - x1 = new Displacement1D(dxb1, dxc1); - y1 = new Displacement1D(dyb1, dyc1); - } - - public void draw(Graphics g, int x, int y, int width, int height) - { - g.drawLine(x0.xform(x, width), - y0.xform(y, height), - x1.xform(x, width), - y1.xform(y, height)); - } -} +package ecologylab.generic; + +import java.awt.Graphics; + +/** + * A 2D line, as defined by parametric coefficients. + * The line, ultimately will be defined by 2 end points, that is, by 4 + * integers, when it is drawn. + * The parametric representation is of the form: + * x0 = a*x + b*width + c, + * y0 = a*y + b*height + c. + * + * Displacement1D holds these parametric forms. + * In our world a=1, always, so we assume that, and dont bother with + * the extra multiplication. (This could always be changed inside the + * encapsulated Displacement1D, without effecting the call sites.) + */ +public class Line2D +{ + Displacement1D x0, y0, x1, y1; + + public Line2D(int[] dx0, int[] dy0, int[] dx1, int[] dy1) + { + x0 = new Displacement1D(dx0); + } + public Line2D(int[] dx0) + { + x0 = new Displacement1D(dx0); + } + public Line2D(int dxb0, int dxc0, int dyb0, int dyc0, + int dxb1, int dxc1, int dyb1, int dyc1) + { + x0 = new Displacement1D(dxb0, dxc0); + y0 = new Displacement1D(dyb0, dyc0); + x1 = new Displacement1D(dxb1, dxc1); + y1 = new Displacement1D(dyb1, dyc1); + } + + public void draw(Graphics g, int x, int y, int width, int height) + { + g.drawLine(x0.xform(x, width), + y0.xform(y, height), + x1.xform(x, width), + y1.xform(y, height)); + } +} diff --git a/simplCore/src/ecologylab/generic/MathTools.java b/simplCore/src/ecologylab/generic/MathTools.java index ed199a17..35b9b9ff 100644 --- a/simplCore/src/ecologylab/generic/MathTools.java +++ b/simplCore/src/ecologylab/generic/MathTools.java @@ -1,143 +1,143 @@ -/* - * Compiled by Andruid Kerne, Texas A&M University and Creating Media LLC. - * Copyright 1996-2002 by Andruid Kerne. - * Use freely without profit, so long as this notice is included intact. - */ -package ecologylab.generic; - -import java.util.Vector; - -/** - * Mathematical tools for shaping ranges of values; - * wrappers beyond @link java.lang.Math. - * Includes various falvors of random. - */ -public class MathTools -{ - MathTools() {} - /** - * @return a random float (instead of a double) - */ - public static float random() { return (float) Math.random(); } - /** - * @return a random integer <= max - */ - public static int rand(int max) - { - return (int) (Math.random() * (max + 1)); - } - // an int: [0, max - 1] - /** - * @return a random integer < max - */ - public static int random(int max) - { - return (int) (Math.random() * max); - } - /** - * @return a random float < max - */ - public static float random(float max) - { - return (float) Math.random() * max; - } - /** - * heads i win. tails you lose. - */ - public static boolean tossCoin() { return rand(1) == 1; } - /** - * @param choices := array of pairs; - * each pair := [value, probability] - */ - public static float pick(float[][] choices) - { - float sum = 0, indicator, bracket = 0; - for (int i=0; i != choices.length; i++) - sum += choices[i][1]; - indicator = (float) Math.random() * sum; - for (int i=0; i != choices.length; i++) - { - bracket += choices[i][1]; - if (indicator <= bracket) - return choices[i][0]; - } - throw new Error("MoreMath.pick() didnt pick any"); - } - - public static Vector randomize(Vector v) - { - // swap the random pick with the ith pick (starts w the last one) - // then do it again, without the last one (its been randomized) - for (int i=v.size(); i != 0; i--) - { - int pick = (int) (Math.random() * i); - // swap em - Object o = v.elementAt(i - 1); - v.setElementAt(v.elementAt(pick), i - 1); - v.setElementAt(o, pick); - } - return v; - } - - /** - * push a to 1 extreme or the other, based on b - */ - public static float bias(float a, float b) - { - if (a < .001) - return 0; - else if (a > .999) - return 1; - else if (b < .001) - return 0; - else if (b > .999) - return 1; - else - return (float)(Math.pow(a, Math.log(b) / Math.log(0.5))); - } - /** - * push a towards middle (b < .5), or extrema (b > .5). - * - * could also be called "contrast". - */ - public static float gain(float a, float b) - { - float p; - - if (a < .001f) - return 0; - else if (a > .999) - return 1; - b = (b < .001f) ? .001f : (b > .999f) ? .999f : b; - p = (float) (Math.log(1 - b) / Math.log(0.5f)); - if (a < 0.5f) - return (float) (Math.pow(2 * a, p) / 2); - else - return (float) (1 - Math.pow(2 * (1 - a), p) / 2); - } - public static float randGain(float factor) - { return MathTools.gain(random(), factor); } - public static float randBias(float factor) - { return MathTools.bias(random(), factor); } - /** - * plus or minus - * @param op is 0 to 1 - */ - public static float pM(float op, float factor) - { return (op - .5f) * factor;} - - /** - * random plus or minus - * @param factor the magnitude of the desired result. - * - * @return a random number in the interval [-factor, factor]. - */ - public static float randPM(float factor) - { return pM(random(), factor);} - - public static float toExtremes(float x) - { - float factor = bias(random(), .8f); - return gain(x, factor); - } -} +/* + * Compiled by Andruid Kerne, Texas A&M University and Creating Media LLC. + * Copyright 1996-2002 by Andruid Kerne. + * Use freely without profit, so long as this notice is included intact. + */ +package ecologylab.generic; + +import java.util.Vector; + +/** + * Mathematical tools for shaping ranges of values; + * wrappers beyond @link java.lang.Math. + * Includes various falvors of random. + */ +public class MathTools +{ + MathTools() {} + /** + * @return a random float (instead of a double) + */ + public static float random() { return (float) Math.random(); } + /** + * @return a random integer <= max + */ + public static int rand(int max) + { + return (int) (Math.random() * (max + 1)); + } + // an int: [0, max - 1] + /** + * @return a random integer < max + */ + public static int random(int max) + { + return (int) (Math.random() * max); + } + /** + * @return a random float < max + */ + public static float random(float max) + { + return (float) Math.random() * max; + } + /** + * heads i win. tails you lose. + */ + public static boolean tossCoin() { return rand(1) == 1; } + /** + * @param choices := array of pairs; + * each pair := [value, probability] + */ + public static float pick(float[][] choices) + { + float sum = 0, indicator, bracket = 0; + for (int i=0; i != choices.length; i++) + sum += choices[i][1]; + indicator = (float) Math.random() * sum; + for (int i=0; i != choices.length; i++) + { + bracket += choices[i][1]; + if (indicator <= bracket) + return choices[i][0]; + } + throw new Error("MoreMath.pick() didnt pick any"); + } + + public static Vector randomize(Vector v) + { + // swap the random pick with the ith pick (starts w the last one) + // then do it again, without the last one (its been randomized) + for (int i=v.size(); i != 0; i--) + { + int pick = (int) (Math.random() * i); + // swap em + Object o = v.elementAt(i - 1); + v.setElementAt(v.elementAt(pick), i - 1); + v.setElementAt(o, pick); + } + return v; + } + + /** + * push a to 1 extreme or the other, based on b + */ + public static float bias(float a, float b) + { + if (a < .001) + return 0; + else if (a > .999) + return 1; + else if (b < .001) + return 0; + else if (b > .999) + return 1; + else + return (float)(Math.pow(a, Math.log(b) / Math.log(0.5))); + } + /** + * push a towards middle (b < .5), or extrema (b > .5). + * + * could also be called "contrast". + */ + public static float gain(float a, float b) + { + float p; + + if (a < .001f) + return 0; + else if (a > .999) + return 1; + b = (b < .001f) ? .001f : (b > .999f) ? .999f : b; + p = (float) (Math.log(1 - b) / Math.log(0.5f)); + if (a < 0.5f) + return (float) (Math.pow(2 * a, p) / 2); + else + return (float) (1 - Math.pow(2 * (1 - a), p) / 2); + } + public static float randGain(float factor) + { return MathTools.gain(random(), factor); } + public static float randBias(float factor) + { return MathTools.bias(random(), factor); } + /** + * plus or minus + * @param op is 0 to 1 + */ + public static float pM(float op, float factor) + { return (op - .5f) * factor;} + + /** + * random plus or minus + * @param factor the magnitude of the desired result. + * + * @return a random number in the interval [-factor, factor]. + */ + public static float randPM(float factor) + { return pM(random(), factor);} + + public static float toExtremes(float x) + { + float factor = bias(random(), .8f); + return gain(x, factor); + } +} diff --git a/simplCore/src/ecologylab/generic/MultiIndexer.java b/simplCore/src/ecologylab/generic/MultiIndexer.java index 6d9c689b..df6950f7 100644 --- a/simplCore/src/ecologylab/generic/MultiIndexer.java +++ b/simplCore/src/ecologylab/generic/MultiIndexer.java @@ -1,115 +1,110 @@ -package ecologylab.generic; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; - -/** - * 1-3 - * 420-450; :3 - * - * A class that indexes inserted objects by a set of multiple criteria. implementors provide the critera in the form of - * ItemIndexer predicates, marshalling happens via .by(); - * @author tom - * - */ -public abstract class MultiIndexer { - - public final class InnerIndexer{ - - Map ourMap; - - public InnerIndexer(Map theMap) - { - this.ourMap = theMap; - } - - public IndexedObject get(String indexString) - { - return this.ourMap.get(indexString); - } - - } - - private HashMap> allmaps; - private List allitems; - - public MultiIndexer() - { - this.allitems = new ArrayList(); // Not sure about this one... may revise. - // This is probably better as a set, but I can't decide at the moment. - this.allmaps = new HashMap>(); - - // Initialize all of the maps in the allmaps. - for(ItemIndexPredicate index : this.getIndexPredicates()) - { - String indexID = index.GetIndexIdentifier(); - - if(this.allmaps.containsKey(indexID)) - { - throw new RuntimeException("Should not have multiple indexers of the same identifer, please check your indexers and try again."); - }else{ - // Put a new map at the approrpiate index. - this.allmaps.put(indexID, new HashMap()); - } - } - } - - /** - * Obtains the list of index predicates that implementors of the MultiIndexer desire. - * Guides the indexing process.. - * @return - */ - public abstract List> getIndexPredicates(); - - /** - * Inserts an item into the MultiIndexer - * @param object - */ - public void Insert(IndexedObject object) - { - this.allitems.add(object); - - for(ItemIndexPredicate index : this.getIndexPredicates()) - { - String indexID = index.GetIndexIdentifier(); - - String indexValue = index.ObtainIndex(object); - - this.allmaps.get(indexID).put(indexValue, object); - } - } - - /** - * Removes a given item from the Multiindexer - * @param object - */ - public void Remove(IndexedObject object) - { - this.allitems.remove(object); - - for(ItemIndexPredicate index : this.getIndexPredicates()) - { - String indexID = index.GetIndexIdentifier(); - - String indexValue = index.ObtainIndex(object); - - this.allmaps.get(indexID).remove(indexValue); - } - } - - public InnerIndexer by(String indexID) - { - return new InnerIndexer(this.allmaps.get(indexID)); - } - - public Integer size() { - return this.allitems.size(); - } -} +package ecologylab.generic; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 1-3 + * 420-450; :3 + * + * A class that indexes inserted objects by a set of multiple criteria. implementors provide the critera in the form of + * ItemIndexer predicates, marshalling happens via .by(); + * @author tom + * + */ +public abstract class MultiIndexer { + + public final class InnerIndexer{ + + Map ourMap; + + public InnerIndexer(Map theMap) + { + this.ourMap = theMap; + } + + public IndexedObject get(String indexString) + { + return this.ourMap.get(indexString); + } + + } + + private HashMap> allmaps; + private List allitems; + + public MultiIndexer() + { + this.allitems = new ArrayList(); // Not sure about this one... may revise. + // This is probably better as a set, but I can't decide at the moment. + this.allmaps = new HashMap>(); + + // Initialize all of the maps in the allmaps. + for(ItemIndexPredicate index : this.getIndexPredicates()) + { + String indexID = index.GetIndexIdentifier(); + + if(this.allmaps.containsKey(indexID)) + { + throw new RuntimeException("Should not have multiple indexers of the same identifer, please check your indexers and try again."); + }else{ + // Put a new map at the approrpiate index. + this.allmaps.put(indexID, new HashMap()); + } + } + } + + /** + * Obtains the list of index predicates that implementors of the MultiIndexer desire. + * Guides the indexing process.. + * @return + */ + public abstract List> getIndexPredicates(); + + /** + * Inserts an item into the MultiIndexer + * @param object + */ + public void Insert(IndexedObject object) + { + this.allitems.add(object); + + for(ItemIndexPredicate index : this.getIndexPredicates()) + { + String indexID = index.GetIndexIdentifier(); + + String indexValue = index.ObtainIndex(object); + + this.allmaps.get(indexID).put(indexValue, object); + } + } + + /** + * Removes a given item from the Multiindexer + * @param object + */ + public void Remove(IndexedObject object) + { + this.allitems.remove(object); + + for(ItemIndexPredicate index : this.getIndexPredicates()) + { + String indexID = index.GetIndexIdentifier(); + + String indexValue = index.ObtainIndex(object); + + this.allmaps.get(indexID).remove(indexValue); + } + } + + public InnerIndexer by(String indexID) + { + return new InnerIndexer(this.allmaps.get(indexID)); + } + + public Integer size() { + return this.allitems.size(); + } +} diff --git a/simplCore/src/ecologylab/generic/NewPorterStemmer.java b/simplCore/src/ecologylab/generic/NewPorterStemmer.java index 89abbe39..8dc5c7f3 100644 --- a/simplCore/src/ecologylab/generic/NewPorterStemmer.java +++ b/simplCore/src/ecologylab/generic/NewPorterStemmer.java @@ -1,570 +1,570 @@ -package ecologylab.generic; -/* - - Porter stemmer in Java. The original paper is in - - Porter, 1980, An algorithm for suffix stripping, Program, Vol. 14, - no. 3, pp 130-137, - - See also http://www.tartarus.org/~martin/PorterStemmer - - History: - - Release 1 - - Bug 1 (reported by Gonzalo Parra 16/10/99) fixed as marked below. - The words 'aed', 'eed', 'oed' leave k at 'a' for step 3, and b[k-1] - is then out outside the bounds of b. - - Release 2 - - Similarly, - - Bug 2 (reported by Steve Dyrdahl 22/2/00) fixed as marked below. - 'ion' by itself leaves j = -1 in the test for 'ion' in step 5, and - b[j] is then outside the bounds of b. - - Release 3 - - Considerably revised 4/9/00 in the light of many helpful suggestions - from Brian Goetz of Quiotix Corporation (brian@quiotix.com). - - Release 4 - - Modification - This version is derived from Release 4, modified by Jin Wang to use - StringBuffer instead of char array. - -*/ - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; - -/** - * Stemmer, implementing the Porter Stemming Algorithm - * - * The Stemmer class transforms a word into its root form. The input - * word can be provided a character at time (by calling add()), or at once - * by calling one of the various stem(something) methods. - * - * New version of PorterStemmer implemented with StringBuffer. - */ - -public class NewPorterStemmer -extends Debug -{ - //private char[] b; - private StringBuffer b; - private int i, /* offset into b */ - i_end, /* offset to end of stemmed word */ - j, k; - - private boolean dirty = false; - private static final int INC = 256; - /* unit of size whereby b is increased */ - public NewPorterStemmer() - { - b = new StringBuffer(INC); - i = 0; - i_end = 0; - } - - /** - * reset() resets the stemmer so it can stem another word. If you invoke - * the stemmer by calling add(char) and then stem(), you must call reset() - * before starting another word. - */ - public void reset() - { - i = 0; - dirty = false; - } - - /** - * Add a character to the word being stemmed. When you are finished - * adding characters, you can call stem(void) to stem the word. - */ - - public void add(char ch) - { - if (i == b.length()) - b.setLength(i+INC); - b.setCharAt(i++, ch); - } - - /** Adds wLen characters to the word being stemmed contained in a portion - * of a char[] array. This is like repeated calls of add(char ch), but - * faster. - */ - - public void add(char[] w, int wLen) - { - if (i+wLen >= b.length()) - b.setLength(i+wLen+INC); - for (int c = 0; c < wLen; c++) - b.setCharAt(i++, w[c]); - - } - public void add(String s) - { - reset(); - - int wLen = s.length(); - b.setLength(wLen); - - for (int c = 0; c < wLen; c++) - b.setCharAt(i++, s.charAt(c)); - } -/* - public void add(String s) - { - add(s.toCharArray(), s.length()); - } - */ - /** - * After a word has been stemmed, it can be retrieved by toString(), - * or a reference to the internal buffer can be retrieved by getResultBuffer - * and getResultLength (which is generally more efficient.) - */ - @Override -public String toString() - { - // force ArrayCopy here, otherwise StringBuffer gets shared and SLOW - return b.substring(0, i_end); -// return new String(b,0,i_end); - } - - public String stem(String s) - { -/* - NewPorterStemmer stemmer = new NewPorterStemmer(); - stemmer.add(s); - stemmer.stem(); - return stemmer.toString(); - */ - add(s); - stem(); - return toString(); - } - /** - * Returns the length of the word resulting from the stemming process. - */ - public int getResultLength() { return i_end; } - - /** - * Returns a reference to a character buffer containing the results of - * the stemming process. You also need to consult getResultLength() - * to determine the length of the result. - */ - public StringBuffer getResultBuffer() { return b; } - - /* cons(i) is true <=> b[i] is a consonant. */ - - private final boolean cons(int i) - { - switch (b.charAt(i)) - { case 'a': case 'e': case 'i': case 'o': case 'u': return false; - case 'y': return (i==0) ? true : !cons(i-1); - default: return true; - } - } - - /* m() measures the number of consonant sequences between 0 and j. if c is - a consonant sequence and v a vowel sequence, and <..> indicates arbitrary - presence, - - gives 0 - vc gives 1 - vcvc gives 2 - vcvcvc gives 3 - .... - */ - - private final int m() - { int n = 0; - int i = 0; - while(true) - { if (i > j) return n; - if (! cons(i)) break; i++; - } - i++; - while(true) - { while(true) - { if (i > j) return n; - if (cons(i)) break; - i++; - } - i++; - n++; - while(true) - { if (i > j) return n; - if (! cons(i)) break; - i++; - } - i++; - } - } - - /* vowelinstem() is true <=> 0,...j contains a vowel */ - - private final boolean vowelinstem() - { int i; for (i = 0; i <= j; i++) if (! cons(i)) return true; - return false; - } - - /* doublec(j) is true <=> j,(j-1) contain a double consonant. */ - - private final boolean doublec(int j) - { if (j < 1) return false; - if (b.charAt(j) != b.charAt(j-1)) return false; - return cons(j); - } - - /* cvc(i) is true <=> i-2,i-1,i has the form consonant - vowel - consonant - and also if the second c is not w,x or y. this is used when trying to - restore an e at the end of a short word. e.g. - - cav(e), lov(e), hop(e), crim(e), but - snow, box, tray. - - */ - - private final boolean cvc(int i) - { if (i < 2 || !cons(i) || cons(i-1) || !cons(i-2)) return false; - { int ch = b.charAt(i); - if (ch == 'w' || ch == 'x' || ch == 'y') return false; - } - return true; - } - - private final boolean ends(String s) - { int l = s.length(); - int o = k-l+1; - if (o < 0) return false; - int oTracker = o; - int bLength = b.length(); - for (int i = 0; i < l; i++) - { - if (oTracker++ >= bLength) - return false; - if (b.charAt(o+i) != s.charAt(i)) - return false; - } - j = k-l; - return true; - } - - /* setto(s) sets (j+1),...k to the characters in the string s, readjusting - k. */ - - private final void setto(String s) - { int l = s.length(); - int o = j+1; - for (int i = 0; i < l; i++) b.setCharAt(o+i, s.charAt(i)); - k = j+l; - dirty = true; - } - - /* r(s) is used further down. */ - - private final void r(String s) { if (m() > 0) setto(s); } - - /* step1() gets rid of plurals and -ed or -ing. e.g. - - caresses -> caress - ponies -> poni - ties -> ti - caress -> caress - cats -> cat - - feed -> feed - agreed -> agree - disabled -> disable - - matting -> mat - mating -> mate - meeting -> meet - milling -> mill - messing -> mess - - meetings -> meet - - */ - - private final void step1() - { if (b.charAt(k) == 's') - { if (ends("sses")) k -= 2; else - if (ends("ies")) setto("i"); else - if (b.charAt(k-1) != 's') k--; - } - if (ends("eed")) { if (m() > 0) k--; } else - if ((ends("ed") || ends("ing")) && vowelinstem()) - { k = j; - if (ends("at")) setto("ate"); else - if (ends("bl")) setto("ble"); else - if (ends("iz")) setto("ize"); else - if (doublec(k)) - { k--; - { int ch = b.charAt(k); - if (ch == 'l' || ch == 's' || ch == 'z') k++; - } - } - else if (m() == 1 && cvc(k)) setto("e"); - } - } - - /* step2() turns terminal y to i when there is another vowel in the stem. */ - - private final void step2() - { - if (ends("y") && vowelinstem()) - b.setCharAt(k,'i'); - dirty = true; - } - /* step3() maps double suffices to single ones. so -ization ( = -ize plus - -ation) maps to -ize etc. note that the string before the suffix must give - m() > 0. */ - - private final void step3() - { - if (k == 0) - return; /* For Bug 1 */ - switch (b.charAt(k-1)) - { - case 'a': if (ends("ational")) { r("ate"); break; } - if (ends("tional")) { r("tion"); break; } - break; - case 'c': if (ends("enci")) { r("ence"); break; } - if (ends("anci")) { r("ance"); break; } - break; - case 'e': if (ends("izer")) { r("ize"); break; } - break; - case 'l': if (ends("bli")) { r("ble"); break; } - if (ends("alli")) { r("al"); break; } - if (ends("entli")) { r("ent"); break; } - if (ends("eli")) { r("e"); break; } - if (ends("ousli")) { r("ous"); break; } - break; - case 'o': if (ends("ization")) { r("ize"); break; } - if (ends("ation")) { r("ate"); break; } - if (ends("ator")) { r("ate"); break; } - break; - case 's': if (ends("alism")) { r("al"); break; } - if (ends("iveness")) { r("ive"); break; } - if (ends("fulness")) { r("ful"); break; } - if (ends("ousness")) { r("ous"); break; } - break; - case 't': if (ends("aliti")) { r("al"); break; } - if (ends("iviti")) { r("ive"); break; } - if (ends("biliti")) { r("ble"); break; } - break; - case 'g': if (ends("logi")) { r("log"); break; } - } - } - - /* step4() deals with -ic-, -full, -ness etc. similar strategy to step3. */ - - private final void step4() - { - switch (b.charAt(k)) - { - case 'e': if (ends("icate")) { r("ic"); break; } - if (ends("ative")) { r(""); break; } - if (ends("alize")) { r("al"); break; } - break; - case 'i': if (ends("iciti")) { r("ic"); break; } - break; - case 'l': if (ends("ical")) { r("ic"); break; } - if (ends("ful")) { r(""); break; } - break; - case 's': if (ends("ness")) { r(""); break; } - break; - } - } - - /* step5() takes off -ant, -ence etc., in context vcvc. */ - - private final void step5() - { - if (k == 0) - return; /* for Bug 1 */ - switch (b.charAt(k-1)) - { - case 'a': - if (ends("al")) - break; - return; - case 'c': - if (ends("ance")) - break; - if (ends("ence")) - break; - return; - case 'e': - if (ends("er")) - break; - return; - case 'i': - if (ends("ic")) - break; - return; - case 'l': - if (ends("able")) - break; - if (ends("ible")) - break; - return; - case 'n': - if (ends("ant")) - break; - if (ends("ement")) - break; - if (ends("ment")) - break; - /* element etc. not stripped before the m */ - if (ends("ent")) - break; - return; - case 'o': - if (ends("ion") && j >= 0 && - (b.charAt(j) == 's' || b.charAt(j) == 't')) - break; /* j >= 0 fixes Bug 2 */ - if (ends("ou")) - break; - return; - /* takes care of -ous */ - case 's': - if (ends("ism")) - break; - return; - case 't': - if (ends("ate")) - break; - if (ends("iti")) - break; - return; - case 'u': - if (ends("ous")) - break; - return; - case 'v': - if (ends("ive")) - break; - return; - case 'z': - if (ends("ize")) - break; - return; - default: return; - } - if (m() > 1) - k = j; - } - - /* step6() removes a final -e if m() > 1. */ - - private final void step6() - { - j = k; - if (b.charAt(k) == 'e') - { int a = m(); - if (a > 1 || a == 1 && !cvc(k-1)) - k--; - } - if (b.charAt(k) == 'l' && doublec(k) && m() > 1) - k--; - } - - /** Stem the word placed into the Stemmer buffer through calls to add(). - * Returns true if the stemming process resulted in a word different - * from the input. You can retrieve the result with - * getResultLength()/getResultBuffer() or toString(). - */ - public void stem() - { k = i - 1; - if (k > 1) { - step1(); - step2(); - step3(); - step4(); - step5(); - step6(); } - i_end = k+1; i = 0; - } - - /** Test program for demonstrating the PorterStemmer. It reads text from a - * a list of files, stems each word, and writes the result to standard - * output. Note that the word stemmed is expected to be in lower case: - * forcing lower case must be done outside the PorterStemmer class. - * Usage: PorterStemmer file-name file-name ... - */ - public static void main(String[] args) - { - char[] w = new char[501]; - NewPorterStemmer s = new NewPorterStemmer(); - //String test = "computers"; - //System.out.println("testString is " + s.stem(test)); - for (int i = 0; i < args.length; i++) - try - { - FileInputStream in = new FileInputStream(args[i]); - - try - { while(true) - - { int ch = in.read(); - if (Character.isLetter((char) ch)) - { - int j = 0; - while(true) - { ch = Character.toLowerCase((char) ch); - w[j] = (char) ch; - if (j < 500) j++; - ch = in.read(); - if (!Character.isLetter((char) ch)) - { - /* to test add(char ch) */ - for (int c = 0; c < j; c++) - - s.add(w[c]); - //System.out.println(s.toString()); - - - /* or, to test add(char[] w, int j) */ - //s.add(w, j); - - s.stem(); - - { String u; - - /* and now, to test toString() : */ - - u = s.toString(); - /* to test getResultBuffer(), getResultLength() : */ - /* u = new String(s.getResultBuffer(), 0, s.getResultLength()); */ - - System.out.print(u); - } - break; - } - } - } - if (ch < 0) break; - System.out.print((char)ch); - } - } - catch (IOException e) - { System.out.println("error reading " + args[i]); - break; - } - } - catch (FileNotFoundException e) - { System.out.println("file " + args[i] + " not found"); - break; - } - } -} - - - +package ecologylab.generic; +/* + + Porter stemmer in Java. The original paper is in + + Porter, 1980, An algorithm for suffix stripping, Program, Vol. 14, + no. 3, pp 130-137, + + See also http://www.tartarus.org/~martin/PorterStemmer + + History: + + Release 1 + + Bug 1 (reported by Gonzalo Parra 16/10/99) fixed as marked below. + The words 'aed', 'eed', 'oed' leave k at 'a' for step 3, and b[k-1] + is then out outside the bounds of b. + + Release 2 + + Similarly, + + Bug 2 (reported by Steve Dyrdahl 22/2/00) fixed as marked below. + 'ion' by itself leaves j = -1 in the test for 'ion' in step 5, and + b[j] is then outside the bounds of b. + + Release 3 + + Considerably revised 4/9/00 in the light of many helpful suggestions + from Brian Goetz of Quiotix Corporation (brian@quiotix.com). + + Release 4 + + Modification + This version is derived from Release 4, modified by Jin Wang to use + StringBuffer instead of char array. + +*/ + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +/** + * Stemmer, implementing the Porter Stemming Algorithm + * + * The Stemmer class transforms a word into its root form. The input + * word can be provided a character at time (by calling add()), or at once + * by calling one of the various stem(something) methods. + * + * New version of PorterStemmer implemented with StringBuffer. + */ + +public class NewPorterStemmer +extends Debug +{ + //private char[] b; + private StringBuffer b; + private int i, /* offset into b */ + i_end, /* offset to end of stemmed word */ + j, k; + + private boolean dirty = false; + private static final int INC = 256; + /* unit of size whereby b is increased */ + public NewPorterStemmer() + { + b = new StringBuffer(INC); + i = 0; + i_end = 0; + } + + /** + * reset() resets the stemmer so it can stem another word. If you invoke + * the stemmer by calling add(char) and then stem(), you must call reset() + * before starting another word. + */ + public void reset() + { + i = 0; + dirty = false; + } + + /** + * Add a character to the word being stemmed. When you are finished + * adding characters, you can call stem(void) to stem the word. + */ + + public void add(char ch) + { + if (i == b.length()) + b.setLength(i+INC); + b.setCharAt(i++, ch); + } + + /** Adds wLen characters to the word being stemmed contained in a portion + * of a char[] array. This is like repeated calls of add(char ch), but + * faster. + */ + + public void add(char[] w, int wLen) + { + if (i+wLen >= b.length()) + b.setLength(i+wLen+INC); + for (int c = 0; c < wLen; c++) + b.setCharAt(i++, w[c]); + + } + public void add(String s) + { + reset(); + + int wLen = s.length(); + b.setLength(wLen); + + for (int c = 0; c < wLen; c++) + b.setCharAt(i++, s.charAt(c)); + } +/* + public void add(String s) + { + add(s.toCharArray(), s.length()); + } + */ + /** + * After a word has been stemmed, it can be retrieved by toString(), + * or a reference to the internal buffer can be retrieved by getResultBuffer + * and getResultLength (which is generally more efficient.) + */ + @Override +public String toString() + { + // force ArrayCopy here, otherwise StringBuffer gets shared and SLOW + return b.substring(0, i_end); +// return new String(b,0,i_end); + } + + public String stem(String s) + { +/* + NewPorterStemmer stemmer = new NewPorterStemmer(); + stemmer.add(s); + stemmer.stem(); + return stemmer.toString(); + */ + add(s); + stem(); + return toString(); + } + /** + * Returns the length of the word resulting from the stemming process. + */ + public int getResultLength() { return i_end; } + + /** + * Returns a reference to a character buffer containing the results of + * the stemming process. You also need to consult getResultLength() + * to determine the length of the result. + */ + public StringBuffer getResultBuffer() { return b; } + + /* cons(i) is true <=> b[i] is a consonant. */ + + private final boolean cons(int i) + { + switch (b.charAt(i)) + { case 'a': case 'e': case 'i': case 'o': case 'u': return false; + case 'y': return (i==0) ? true : !cons(i-1); + default: return true; + } + } + + /* m() measures the number of consonant sequences between 0 and j. if c is + a consonant sequence and v a vowel sequence, and <..> indicates arbitrary + presence, + + gives 0 + vc gives 1 + vcvc gives 2 + vcvcvc gives 3 + .... + */ + + private final int m() + { int n = 0; + int i = 0; + while(true) + { if (i > j) return n; + if (! cons(i)) break; i++; + } + i++; + while(true) + { while(true) + { if (i > j) return n; + if (cons(i)) break; + i++; + } + i++; + n++; + while(true) + { if (i > j) return n; + if (! cons(i)) break; + i++; + } + i++; + } + } + + /* vowelinstem() is true <=> 0,...j contains a vowel */ + + private final boolean vowelinstem() + { int i; for (i = 0; i <= j; i++) if (! cons(i)) return true; + return false; + } + + /* doublec(j) is true <=> j,(j-1) contain a double consonant. */ + + private final boolean doublec(int j) + { if (j < 1) return false; + if (b.charAt(j) != b.charAt(j-1)) return false; + return cons(j); + } + + /* cvc(i) is true <=> i-2,i-1,i has the form consonant - vowel - consonant + and also if the second c is not w,x or y. this is used when trying to + restore an e at the end of a short word. e.g. + + cav(e), lov(e), hop(e), crim(e), but + snow, box, tray. + + */ + + private final boolean cvc(int i) + { if (i < 2 || !cons(i) || cons(i-1) || !cons(i-2)) return false; + { int ch = b.charAt(i); + if (ch == 'w' || ch == 'x' || ch == 'y') return false; + } + return true; + } + + private final boolean ends(String s) + { int l = s.length(); + int o = k-l+1; + if (o < 0) return false; + int oTracker = o; + int bLength = b.length(); + for (int i = 0; i < l; i++) + { + if (oTracker++ >= bLength) + return false; + if (b.charAt(o+i) != s.charAt(i)) + return false; + } + j = k-l; + return true; + } + + /* setto(s) sets (j+1),...k to the characters in the string s, readjusting + k. */ + + private final void setto(String s) + { int l = s.length(); + int o = j+1; + for (int i = 0; i < l; i++) b.setCharAt(o+i, s.charAt(i)); + k = j+l; + dirty = true; + } + + /* r(s) is used further down. */ + + private final void r(String s) { if (m() > 0) setto(s); } + + /* step1() gets rid of plurals and -ed or -ing. e.g. + + caresses -> caress + ponies -> poni + ties -> ti + caress -> caress + cats -> cat + + feed -> feed + agreed -> agree + disabled -> disable + + matting -> mat + mating -> mate + meeting -> meet + milling -> mill + messing -> mess + + meetings -> meet + + */ + + private final void step1() + { if (b.charAt(k) == 's') + { if (ends("sses")) k -= 2; else + if (ends("ies")) setto("i"); else + if (b.charAt(k-1) != 's') k--; + } + if (ends("eed")) { if (m() > 0) k--; } else + if ((ends("ed") || ends("ing")) && vowelinstem()) + { k = j; + if (ends("at")) setto("ate"); else + if (ends("bl")) setto("ble"); else + if (ends("iz")) setto("ize"); else + if (doublec(k)) + { k--; + { int ch = b.charAt(k); + if (ch == 'l' || ch == 's' || ch == 'z') k++; + } + } + else if (m() == 1 && cvc(k)) setto("e"); + } + } + + /* step2() turns terminal y to i when there is another vowel in the stem. */ + + private final void step2() + { + if (ends("y") && vowelinstem()) + b.setCharAt(k,'i'); + dirty = true; + } + /* step3() maps double suffices to single ones. so -ization ( = -ize plus + -ation) maps to -ize etc. note that the string before the suffix must give + m() > 0. */ + + private final void step3() + { + if (k == 0) + return; /* For Bug 1 */ + switch (b.charAt(k-1)) + { + case 'a': if (ends("ational")) { r("ate"); break; } + if (ends("tional")) { r("tion"); break; } + break; + case 'c': if (ends("enci")) { r("ence"); break; } + if (ends("anci")) { r("ance"); break; } + break; + case 'e': if (ends("izer")) { r("ize"); break; } + break; + case 'l': if (ends("bli")) { r("ble"); break; } + if (ends("alli")) { r("al"); break; } + if (ends("entli")) { r("ent"); break; } + if (ends("eli")) { r("e"); break; } + if (ends("ousli")) { r("ous"); break; } + break; + case 'o': if (ends("ization")) { r("ize"); break; } + if (ends("ation")) { r("ate"); break; } + if (ends("ator")) { r("ate"); break; } + break; + case 's': if (ends("alism")) { r("al"); break; } + if (ends("iveness")) { r("ive"); break; } + if (ends("fulness")) { r("ful"); break; } + if (ends("ousness")) { r("ous"); break; } + break; + case 't': if (ends("aliti")) { r("al"); break; } + if (ends("iviti")) { r("ive"); break; } + if (ends("biliti")) { r("ble"); break; } + break; + case 'g': if (ends("logi")) { r("log"); break; } + } + } + + /* step4() deals with -ic-, -full, -ness etc. similar strategy to step3. */ + + private final void step4() + { + switch (b.charAt(k)) + { + case 'e': if (ends("icate")) { r("ic"); break; } + if (ends("ative")) { r(""); break; } + if (ends("alize")) { r("al"); break; } + break; + case 'i': if (ends("iciti")) { r("ic"); break; } + break; + case 'l': if (ends("ical")) { r("ic"); break; } + if (ends("ful")) { r(""); break; } + break; + case 's': if (ends("ness")) { r(""); break; } + break; + } + } + + /* step5() takes off -ant, -ence etc., in context vcvc. */ + + private final void step5() + { + if (k == 0) + return; /* for Bug 1 */ + switch (b.charAt(k-1)) + { + case 'a': + if (ends("al")) + break; + return; + case 'c': + if (ends("ance")) + break; + if (ends("ence")) + break; + return; + case 'e': + if (ends("er")) + break; + return; + case 'i': + if (ends("ic")) + break; + return; + case 'l': + if (ends("able")) + break; + if (ends("ible")) + break; + return; + case 'n': + if (ends("ant")) + break; + if (ends("ement")) + break; + if (ends("ment")) + break; + /* element etc. not stripped before the m */ + if (ends("ent")) + break; + return; + case 'o': + if (ends("ion") && j >= 0 && + (b.charAt(j) == 's' || b.charAt(j) == 't')) + break; /* j >= 0 fixes Bug 2 */ + if (ends("ou")) + break; + return; + /* takes care of -ous */ + case 's': + if (ends("ism")) + break; + return; + case 't': + if (ends("ate")) + break; + if (ends("iti")) + break; + return; + case 'u': + if (ends("ous")) + break; + return; + case 'v': + if (ends("ive")) + break; + return; + case 'z': + if (ends("ize")) + break; + return; + default: return; + } + if (m() > 1) + k = j; + } + + /* step6() removes a final -e if m() > 1. */ + + private final void step6() + { + j = k; + if (b.charAt(k) == 'e') + { int a = m(); + if (a > 1 || a == 1 && !cvc(k-1)) + k--; + } + if (b.charAt(k) == 'l' && doublec(k) && m() > 1) + k--; + } + + /** Stem the word placed into the Stemmer buffer through calls to add(). + * Returns true if the stemming process resulted in a word different + * from the input. You can retrieve the result with + * getResultLength()/getResultBuffer() or toString(). + */ + public void stem() + { k = i - 1; + if (k > 1) { + step1(); + step2(); + step3(); + step4(); + step5(); + step6(); } + i_end = k+1; i = 0; + } + + /** Test program for demonstrating the PorterStemmer. It reads text from a + * a list of files, stems each word, and writes the result to standard + * output. Note that the word stemmed is expected to be in lower case: + * forcing lower case must be done outside the PorterStemmer class. + * Usage: PorterStemmer file-name file-name ... + */ + public static void main(String[] args) + { + char[] w = new char[501]; + NewPorterStemmer s = new NewPorterStemmer(); + //String test = "computers"; + //System.out.println("testString is " + s.stem(test)); + for (int i = 0; i < args.length; i++) + try + { + FileInputStream in = new FileInputStream(args[i]); + + try + { while(true) + + { int ch = in.read(); + if (Character.isLetter((char) ch)) + { + int j = 0; + while(true) + { ch = Character.toLowerCase((char) ch); + w[j] = (char) ch; + if (j < 500) j++; + ch = in.read(); + if (!Character.isLetter((char) ch)) + { + /* to test add(char ch) */ + for (int c = 0; c < j; c++) + + s.add(w[c]); + //System.out.println(s.toString()); + + + /* or, to test add(char[] w, int j) */ + //s.add(w, j); + + s.stem(); + + { String u; + + /* and now, to test toString() : */ + + u = s.toString(); + /* to test getResultBuffer(), getResultLength() : */ + /* u = new String(s.getResultBuffer(), 0, s.getResultLength()); */ + + System.out.print(u); + } + break; + } + } + } + if (ch < 0) break; + System.out.print((char)ch); + } + } + catch (IOException e) + { System.out.println("error reading " + args[i]); + break; + } + } + catch (FileNotFoundException e) + { System.out.println("file " + args[i] + " not found"); + break; + } + } +} + + + diff --git a/simplCore/src/ecologylab/generic/Noise.java b/simplCore/src/ecologylab/generic/Noise.java index e6351d4c..da8ae924 100644 --- a/simplCore/src/ecologylab/generic/Noise.java +++ b/simplCore/src/ecologylab/generic/Noise.java @@ -1,123 +1,123 @@ -package ecologylab.generic; - -import java.util.Random; - -/** - * Perlin Noise on tap. - */ -public class Noise -{ - static private final int B = 0x100; - static private final int BP = 8; - static private final int BM = 0xff; - - static private final int N = 0x1000; - static private final int NP = 12; - static private final int NM = 0xfff; - - static private int p[] = new int[B + B +2]; - static private double g2[][] = new double[B + B + 2][2]; - static private double g1[] = new double[B + B +2]; - - public static double noise(double arg) - { - int bx0, bx1; - double rx0, rx1, sx, t, u, v; - - t = arg + N; - bx0 = ((int)t)&BM; - bx1 = (bx0+1)&BM; - rx0 = t - (int) t; - rx1 = rx0 -1; - - sx = rx0*rx0*(3.0 - 2.0 * rx0); - u = rx0 * g1[p[bx0]]; - v = rx1 * g1[p[bx1]]; - - return (lerp(sx, u, v)); - } - - static private double noise2(float vec[]) - { - int bx0, bx1, by0, by1, b00, b10, b01, b11; - double rx0, rx1, ry0, ry1, q[], sx, sy, a, b, t, u, v; - int i,j; - - t = vec[0] + N; - bx0 = ((int)t)&BM; - bx1 = (bx0+1)&BM; - rx0 = t - (int) t; - rx1 = rx0 -1; - - t = vec[1] + N; - by0 = ((int)t)&BM; - by1 = (by0+1)&BM; - ry0 = t - (int) t; - ry1 = ry0 -1; - - i = p[ bx0 ]; - j = p[ bx1 ]; - - b00 = p[ i + by0 ]; - b10 = p[ j + by0 ]; - b01 = p[ i + by1 ]; - b11 = p[ j + by1 ]; - - sx = rx0*rx0*(3.0 - 2.0 * rx0); - sy = rx0*rx0*(3.0 - 2.0 * ry0); - - q = g2[ b00 ] ; u = (rx0 * q[0] + ry0 * q[1]); - q = g2[ b10 ] ; v = (rx1 * q[0] + ry0 * q[1]); - a = lerp(sx, u, v); - - q = g2[ b01 ] ; u = (rx0 * q[0] + ry1 * q[1]); - q = g2[ b11 ] ; v = (rx1 * q[0] + ry1 * q[1]); - b = lerp(sx, u, v); - - return lerp(sy,a,b); - } - - - public static double lerp(double t, double a, double b) - { - return a+t*(b-a); - } - - static - { - int i, j, k; - double t; - Random r = new Random(1); - for (i = 0; i < B ; i++) - { - p[i] = i; - t = ((double)(r.nextInt()&BM))/B; - g1[i] = 2.0 * t - 1.0; - - for ( j=0; j<2 ; j++) -// g2[i][j] = (float)((r.nextInt()&BM % (B + B)) -B) /B; - g2[i][j] = (float)(r.nextInt() &BM) / B; - normalize2(g2[i]); - } - while (--i > 0) - { - k = p[i]; - j = r.nextInt() & BM; - p[i] = p[j]; - p[j] = k; - } - for (i = 0; i < B+2; i++) - { - p[B+i] = p[i]; - g1[B+i] = g1[i]; - } - } - static private void normalize2(double v[]) - { - double s; - - s = Math.sqrt(v[0] * v[0] + v[1] * v[1]); - v[0] = v[0] / s; - v[1] = v[1] / s; - } -} +package ecologylab.generic; + +import java.util.Random; + +/** + * Perlin Noise on tap. + */ +public class Noise +{ + static private final int B = 0x100; + static private final int BP = 8; + static private final int BM = 0xff; + + static private final int N = 0x1000; + static private final int NP = 12; + static private final int NM = 0xfff; + + static private int p[] = new int[B + B +2]; + static private double g2[][] = new double[B + B + 2][2]; + static private double g1[] = new double[B + B +2]; + + public static double noise(double arg) + { + int bx0, bx1; + double rx0, rx1, sx, t, u, v; + + t = arg + N; + bx0 = ((int)t)&BM; + bx1 = (bx0+1)&BM; + rx0 = t - (int) t; + rx1 = rx0 -1; + + sx = rx0*rx0*(3.0 - 2.0 * rx0); + u = rx0 * g1[p[bx0]]; + v = rx1 * g1[p[bx1]]; + + return (lerp(sx, u, v)); + } + + static private double noise2(float vec[]) + { + int bx0, bx1, by0, by1, b00, b10, b01, b11; + double rx0, rx1, ry0, ry1, q[], sx, sy, a, b, t, u, v; + int i,j; + + t = vec[0] + N; + bx0 = ((int)t)&BM; + bx1 = (bx0+1)&BM; + rx0 = t - (int) t; + rx1 = rx0 -1; + + t = vec[1] + N; + by0 = ((int)t)&BM; + by1 = (by0+1)&BM; + ry0 = t - (int) t; + ry1 = ry0 -1; + + i = p[ bx0 ]; + j = p[ bx1 ]; + + b00 = p[ i + by0 ]; + b10 = p[ j + by0 ]; + b01 = p[ i + by1 ]; + b11 = p[ j + by1 ]; + + sx = rx0*rx0*(3.0 - 2.0 * rx0); + sy = rx0*rx0*(3.0 - 2.0 * ry0); + + q = g2[ b00 ] ; u = (rx0 * q[0] + ry0 * q[1]); + q = g2[ b10 ] ; v = (rx1 * q[0] + ry0 * q[1]); + a = lerp(sx, u, v); + + q = g2[ b01 ] ; u = (rx0 * q[0] + ry1 * q[1]); + q = g2[ b11 ] ; v = (rx1 * q[0] + ry1 * q[1]); + b = lerp(sx, u, v); + + return lerp(sy,a,b); + } + + + public static double lerp(double t, double a, double b) + { + return a+t*(b-a); + } + + static + { + int i, j, k; + double t; + Random r = new Random(1); + for (i = 0; i < B ; i++) + { + p[i] = i; + t = ((double)(r.nextInt()&BM))/B; + g1[i] = 2.0 * t - 1.0; + + for ( j=0; j<2 ; j++) +// g2[i][j] = (float)((r.nextInt()&BM % (B + B)) -B) /B; + g2[i][j] = (float)(r.nextInt() &BM) / B; + normalize2(g2[i]); + } + while (--i > 0) + { + k = p[i]; + j = r.nextInt() & BM; + p[i] = p[j]; + p[j] = k; + } + for (i = 0; i < B+2; i++) + { + p[B+i] = p[i]; + g1[B+i] = g1[i]; + } + } + static private void normalize2(double v[]) + { + double s; + + s = Math.sqrt(v[0] * v[0] + v[1] * v[1]); + v[0] = v[0] / s; + v[1] = v[1] / s; + } +} diff --git a/simplCore/src/ecologylab/generic/ObjectOrHashMap.java b/simplCore/src/ecologylab/generic/ObjectOrHashMap.java index 0c96693b..7acb8e3a 100644 --- a/simplCore/src/ecologylab/generic/ObjectOrHashMap.java +++ b/simplCore/src/ecologylab/generic/ObjectOrHashMap.java @@ -1,288 +1,288 @@ -/** - * - */ -package ecologylab.generic; - -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -/** - * An attempt to make an object for storing other objects. If only one object - * exists in the collection, then it is stored here, otherwise it's stored in a - * hashmap where it can be randomly accessed. This is meant primarily for - * applications where you're likely to have a LOT of single entires, but may - * occasionally have a very large number (for example, in a hashmap that maps IP - * address to connection). - * - * ObjectOrHashMap stores a single key value pair, until more than one such pair - * has been specified, then it switches to using a HashMap instead of the pair. - * To avoid constructing too many HashMaps, it never destroys the internal - * HashMap once it has been created. It is assumed that ObjectOrHashMap will - * generally be used in another Collection and when it is removed from that - * Collection, it will be destroyed. - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class ObjectOrHashMap implements Map -{ - private class OOHMEntry implements Map.Entry - { - private K key; - - private V value; - - private Map parent; - - public OOHMEntry(K key, V value, Map parent) - { - this.key = key; - this.value = value; - this.parent = parent; - } - - /** - * @see java.util.Map.Entry#getKey() - */ - @Override - public K getKey() - { - return key; - } - - /** - * @see java.util.Map.Entry#getValue() - */ - @Override - public V getValue() - { - return value; - } - - /** - * @see java.util.Map.Entry#setValue(java.lang.Object) - */ - @Override - public V setValue(V value) - { - this.value = value; - - return this.parent.put(key, value); - } - } - - private K singleKey; - - private V singleValue; - - HashMap mappings; - - public ObjectOrHashMap() - { - - } - - public ObjectOrHashMap(K key, V value) - { - this.singleKey = key; - this.singleValue = value; - } - - private HashMap mappings() - { - HashMap currentMap = mappings; - - if (currentMap == null) - { - currentMap = new HashMap(); - mappings = currentMap; - } - - return currentMap; - } - - /** - * @see java.util.Map#clear() - */ - @Override - public void clear() - { - singleKey = null; - singleValue = null; - if (mappings != null) - mappings.clear(); - } - - /** - * @see java.util.Map#containsKey(java.lang.Object) - */ - @Override - public boolean containsKey(Object key) - { - return singleKey == null ? mappings().containsKey(key) : singleKey - .equals(key); - } - - /** - * @see java.util.Map#containsValue(java.lang.Object) - */ - @Override - public boolean containsValue(Object value) - { - return singleValue == null ? mappings().containsValue(value) - : singleValue.equals(value); - } - - /** - * @see java.util.Map#entrySet() - */ - @Override - public Set> entrySet() - { - if (singleValue != null) - { // just one; we need to make the set - Set> set = new LinkedHashSet>(1); - set.add(new OOHMEntry(singleKey, singleValue, this)); - - return set; - } - else - { - return mappings().entrySet(); - } - } - - /** - * @see java.util.Map#get(java.lang.Object) - */ - @Override - public V get(Object key) - { - return singleValue == null ? mappings().get(key) : singleValue; - } - - /** - * @see java.util.Map#isEmpty() - */ - @Override - public boolean isEmpty() - { - // check single value, then mappings, then if mappings exist, we check - // its emptiness - return singleValue == null || mappings == null || mappings.isEmpty(); - } - - /** - * @see java.util.Map#keySet() - */ - @Override - public Set keySet() - { - if (singleKey == null) - { - return mappings().keySet(); - } - else - { - Set set = new LinkedHashSet(1); - set.add(singleKey); - return set; - } - } - - /** - * @see java.util.Map#put(java.lang.Object, java.lang.Object) - */ - @Override - public V put(K key, V value) - { - if (singleKey != null) - { - mappings().put(singleKey, singleValue); - - this.singleKey = null; - this.singleValue = null; - } - // we already know it's instantiated b/c we just did it - return mappings.put(key, value); - } - - /** - * @see java.util.Map#putAll(java.util.Map) - */ - @Override - public void putAll(Map t) - { - if (singleKey != null) - { - mappings().put(singleKey, singleValue); - } - - mappings.putAll(t); - } - - /** - * @see java.util.Map#remove(java.lang.Object) - */ - @Override - public V remove(Object key) - { - if (singleKey != null && singleKey.equals(key)) - { - singleKey = null; - - V retVal = singleValue; - singleValue = null; - - return retVal; - } - else if (mappings != null) - { - return mappings.remove(key); - } - else - { - return null; - } - } - - /** - * @see java.util.Map#size() - */ - @Override - public int size() - { - return singleKey == null ? (mappings == null ? 0 : mappings.size()) : 1; - } - - /** - * @see java.util.Map#values() - */ - @Override - public Collection values() - { - System.out.println("getting values."); - - if (mappings != null) - { -// System.out.println("mappings are not null."); - - return mappings.values(); - } - else - { - // System.out.println("mappings are null."); - - Collection coll = new LinkedHashSet(1); - - if (singleValue != null) - coll.add(singleValue); - - return coll; - } - } - -} +/** + * + */ +package ecologylab.generic; + +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +/** + * An attempt to make an object for storing other objects. If only one object + * exists in the collection, then it is stored here, otherwise it's stored in a + * hashmap where it can be randomly accessed. This is meant primarily for + * applications where you're likely to have a LOT of single entires, but may + * occasionally have a very large number (for example, in a hashmap that maps IP + * address to connection). + * + * ObjectOrHashMap stores a single key value pair, until more than one such pair + * has been specified, then it switches to using a HashMap instead of the pair. + * To avoid constructing too many HashMaps, it never destroys the internal + * HashMap once it has been created. It is assumed that ObjectOrHashMap will + * generally be used in another Collection and when it is removed from that + * Collection, it will be destroyed. + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class ObjectOrHashMap implements Map +{ + private class OOHMEntry implements Map.Entry + { + private K key; + + private V value; + + private Map parent; + + public OOHMEntry(K key, V value, Map parent) + { + this.key = key; + this.value = value; + this.parent = parent; + } + + /** + * @see java.util.Map.Entry#getKey() + */ + @Override + public K getKey() + { + return key; + } + + /** + * @see java.util.Map.Entry#getValue() + */ + @Override + public V getValue() + { + return value; + } + + /** + * @see java.util.Map.Entry#setValue(java.lang.Object) + */ + @Override + public V setValue(V value) + { + this.value = value; + + return this.parent.put(key, value); + } + } + + private K singleKey; + + private V singleValue; + + HashMap mappings; + + public ObjectOrHashMap() + { + + } + + public ObjectOrHashMap(K key, V value) + { + this.singleKey = key; + this.singleValue = value; + } + + private HashMap mappings() + { + HashMap currentMap = mappings; + + if (currentMap == null) + { + currentMap = new HashMap(); + mappings = currentMap; + } + + return currentMap; + } + + /** + * @see java.util.Map#clear() + */ + @Override + public void clear() + { + singleKey = null; + singleValue = null; + if (mappings != null) + mappings.clear(); + } + + /** + * @see java.util.Map#containsKey(java.lang.Object) + */ + @Override + public boolean containsKey(Object key) + { + return singleKey == null ? mappings().containsKey(key) : singleKey + .equals(key); + } + + /** + * @see java.util.Map#containsValue(java.lang.Object) + */ + @Override + public boolean containsValue(Object value) + { + return singleValue == null ? mappings().containsValue(value) + : singleValue.equals(value); + } + + /** + * @see java.util.Map#entrySet() + */ + @Override + public Set> entrySet() + { + if (singleValue != null) + { // just one; we need to make the set + Set> set = new LinkedHashSet>(1); + set.add(new OOHMEntry(singleKey, singleValue, this)); + + return set; + } + else + { + return mappings().entrySet(); + } + } + + /** + * @see java.util.Map#get(java.lang.Object) + */ + @Override + public V get(Object key) + { + return singleValue == null ? mappings().get(key) : singleValue; + } + + /** + * @see java.util.Map#isEmpty() + */ + @Override + public boolean isEmpty() + { + // check single value, then mappings, then if mappings exist, we check + // its emptiness + return singleValue == null || mappings == null || mappings.isEmpty(); + } + + /** + * @see java.util.Map#keySet() + */ + @Override + public Set keySet() + { + if (singleKey == null) + { + return mappings().keySet(); + } + else + { + Set set = new LinkedHashSet(1); + set.add(singleKey); + return set; + } + } + + /** + * @see java.util.Map#put(java.lang.Object, java.lang.Object) + */ + @Override + public V put(K key, V value) + { + if (singleKey != null) + { + mappings().put(singleKey, singleValue); + + this.singleKey = null; + this.singleValue = null; + } + // we already know it's instantiated b/c we just did it + return mappings.put(key, value); + } + + /** + * @see java.util.Map#putAll(java.util.Map) + */ + @Override + public void putAll(Map t) + { + if (singleKey != null) + { + mappings().put(singleKey, singleValue); + } + + mappings.putAll(t); + } + + /** + * @see java.util.Map#remove(java.lang.Object) + */ + @Override + public V remove(Object key) + { + if (singleKey != null && singleKey.equals(key)) + { + singleKey = null; + + V retVal = singleValue; + singleValue = null; + + return retVal; + } + else if (mappings != null) + { + return mappings.remove(key); + } + else + { + return null; + } + } + + /** + * @see java.util.Map#size() + */ + @Override + public int size() + { + return singleKey == null ? (mappings == null ? 0 : mappings.size()) : 1; + } + + /** + * @see java.util.Map#values() + */ + @Override + public Collection values() + { + System.out.println("getting values."); + + if (mappings != null) + { +// System.out.println("mappings are not null."); + + return mappings.values(); + } + else + { + // System.out.println("mappings are null."); + + Collection coll = new LinkedHashSet(1); + + if (singleValue != null) + coll.add(singleValue); + + return coll; + } + } + +} diff --git a/simplCore/src/ecologylab/generic/ObservableDebug.java b/simplCore/src/ecologylab/generic/ObservableDebug.java index ce05a449..8628ec6d 100644 --- a/simplCore/src/ecologylab/generic/ObservableDebug.java +++ b/simplCore/src/ecologylab/generic/ObservableDebug.java @@ -1,93 +1,93 @@ -package ecologylab.generic; - -import java.util.Observable; - -/** - * An {@link java.util.ArrayList ArrayList}, extended with convenient - * connections to our {@link Debug Debug} methods. - */ -public class ObservableDebug -extends Observable -{ - protected ObservableDebug() - { - } - public final void debug(String message) - { - Debug.println(this, message); - } - public final void weird(String message) - { - Debug.weird(this, message); - } - public final void debugA(String message) - { - Debug.printlnA(this, message); - } - public final void debugI(String message) - { - Debug.printlnI(this, message); - } - - public final void debug(int messageLevel, String message) - { - Debug.println(this, messageLevel, message); - } - - public final void debugA(int level, String message) - { - Debug.printlnA(this, level, message); - } - public final void debugI(int level, String message) - { - Debug.printlnI(this, level, message); - } - - public final String getClassName() - { - return Debug.getClassSimpleName(this); - } - public static void print(String message) - { - Debug.print(message); - } - public static void println(String message) - { - Debug.println(message); - } - public static void println(StringBuffer buffy) - { - Debug.println(buffy); - } - @Override -public String toString() - { - return Debug.toString(this); - } - public static void println(String className, - int messageLevel, String message) - { - Debug.println(className, messageLevel, message); - } - public final boolean show(int messageLevel) - { - return Debug.show(this, messageLevel); - } - public String superString() - { - return super.toString(); - } - - /** - * Print a message about an error, starting with this.toString(). - */ - public void error(String message) - { - Debug.error(this, message); - } - -// protected final void finalize() -// { -// AllocationDebugger.finalized(this); -// } -} +package ecologylab.generic; + +import java.util.Observable; + +/** + * An {@link java.util.ArrayList ArrayList}, extended with convenient + * connections to our {@link Debug Debug} methods. + */ +public class ObservableDebug +extends Observable +{ + protected ObservableDebug() + { + } + public final void debug(String message) + { + Debug.println(this, message); + } + public final void weird(String message) + { + Debug.weird(this, message); + } + public final void debugA(String message) + { + Debug.printlnA(this, message); + } + public final void debugI(String message) + { + Debug.printlnI(this, message); + } + + public final void debug(int messageLevel, String message) + { + Debug.println(this, messageLevel, message); + } + + public final void debugA(int level, String message) + { + Debug.printlnA(this, level, message); + } + public final void debugI(int level, String message) + { + Debug.printlnI(this, level, message); + } + + public final String getClassName() + { + return Debug.getClassSimpleName(this); + } + public static void print(String message) + { + Debug.print(message); + } + public static void println(String message) + { + Debug.println(message); + } + public static void println(StringBuffer buffy) + { + Debug.println(buffy); + } + @Override +public String toString() + { + return Debug.toString(this); + } + public static void println(String className, + int messageLevel, String message) + { + Debug.println(className, messageLevel, message); + } + public final boolean show(int messageLevel) + { + return Debug.show(this, messageLevel); + } + public String superString() + { + return super.toString(); + } + + /** + * Print a message about an error, starting with this.toString(). + */ + public void error(String message) + { + Debug.error(this, message); + } + +// protected final void finalize() +// { +// AllocationDebugger.finalized(this); +// } +} diff --git a/simplCore/src/ecologylab/generic/Palette.java b/simplCore/src/ecologylab/generic/Palette.java index bf0b1d23..30f226d2 100644 --- a/simplCore/src/ecologylab/generic/Palette.java +++ b/simplCore/src/ecologylab/generic/Palette.java @@ -1,351 +1,351 @@ -/* - * Copyright 1996-2002 by Andruid Kerne. All rights reserved. - * CONFIDENTIAL. Use is subject to license terms. - */ -package ecologylab.generic; - -import java.awt.Color; - -/** - * Tools for manipulating color spaces. - */ -public class Palette -extends Debug -{ - static float delta = .085f; - - static final String colorNames[] = - { - "blue", "black", "cyan", "darkGray", "gray", - "green", "lightGray", "magenta", "orange", - "pink", "red", "white", "yellow", - }; - - - static final Color colors[] = - { - Color.blue, Color.black, Color.cyan, Color.darkGray, Color.gray, - Color.green, Color.lightGray, Color.magenta, Color.orange, - Color.pink, Color.red, Color.white, Color.yellow, - }; - - - Palette(){} - - // generate complementary color - public static int Complement(Color c) - { - float hsb[] = new float[3]; - Color.RGBtoHSB (c.getRed(), c.getGreen(), c.getBlue(), hsb); - hsb[0] += .5f; - if (hsb[0] > 1) - hsb[0] -= 1; - return Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]); - } - - public static Color complement(Color c) - { - return new Color(Complement(c)); - } - // return 2 colors delta away from the input - public static void Split(Color input, int[] output) - { - float hsb[] = new float[3]; - float newHue; - Color.RGBtoHSB (input.getRed(), input.getGreen(), input.getBlue(), - hsb); - newHue = (hsb[0] + delta) % 1.0f; - output[0] = Color.HSBtoRGB(newHue, hsb[1], hsb[2]); - newHue = (hsb[0] - delta) % 1.0f; - output[1] = Color.HSBtoRGB(newHue, hsb[1], hsb[2]); - } - - public static Color hsvColor(float h, float s, float v) - { - int rgb[] = rgb(h,s,v); - Color result = new Color(rgb[0], rgb[1], rgb[2]); - //println("Palette.hsvColor("+h+","+s+","+v+") = " + result); - return result; - } - - // hsv to rgb - public static int[] rgb(float hf, float s, float v) - { - float r=0,g=0,b=0; - float h = hf * 6; - if (s == 0) - { - r = v; - g = v; - b = v; - } - else - { - int i = (int) Math.floor(h); - float f = h - i; - float p = v * (1 - s); - float q = v * (1 - s*f); - float t = v * (1 - s*(1-f)); - switch (i) - { - case 0: - r = v; - g = t; - b = p; - break; - case 1: - r = q; - g = v; - b = p; - break; - case 2: - r = p; - g = v; - b = t; - break; - case 3: - r = p; - g = q; - b = v; - break; - case 4: - r = t; - g = p; - b = v; - break; - case 5: - r = v; - g = p; - b = q; - break; - } - } - int rgb[] = new int[3]; - rgb[0] = (int) (r * 255); - rgb[1] = (int) (g * 255); - rgb[2] = (int) (b * 255); -// System.out.println("rgb( " +hf+","+s+","+v+" => "+ -// rgb[0]+","+rgb[1]+","+rgb[2]); - return rgb; - } - - // hsv to rgb - public static void rgb(float hf, float s, float v, float[] result) - { - float r=0,g=0,b=0; - float h = hf * 6; - if (s == 0) - { - r = v; - g = v; - b = v; - } - else - { - int i = (int) Math.floor(h); - float f = h - i; - float p = v * (1 - s); - float q = v * (1 - s*f); - float t = v * (1 - s*(1-f)); - switch (i) - { - case 0: - r = v; - g = t; - b = p; - break; - case 1: - r = q; - g = v; - b = p; - break; - case 2: - r = p; - g = v; - b = t; - break; - case 3: - r = p; - g = q; - b = v; - break; - case 4: - r = t; - g = p; - b = v; - break; - case 5: - r = v; - g = p; - b = q; - break; - } - } - result[0] = r; - result[1] = g; - result[2] = b; - } - - // from rgb to hsv - public static float[] hsv(Color c) - { - // note that when saturation=0, hue is undefined (we'll set to 0) - float hsv[] = new float[3]; - Color.RGBtoHSB (c.getRed(), c.getGreen(), c.getBlue(), hsv); - float f = Math.min(hsv[1],.999f); - hsv[1] = f; - f = Math.min(hsv[2],.999f); - hsv[2] = f; - -// System.out.println("hsv("+c+")="+hsv[0]+","+hsv[1]+","+hsv[2]); - return hsv; - } - - public static float[] myHsv(Color c) - { - return myHsv(c.getRed(), c.getGreen(), c.getBlue()); - } - - public static float[] myHsv(int ri, int gi, int bi) - { - float r = ((float) ri) / 255, - g = ((float) gi) / 255, - b = ((float) bi) / 255; - - float h, s; - int isMax; // 0 red, 1 green, 2 blue - // nb: ties don't effect value calculation - // ties here don't effect hue calculation due to code below - // ties aren't effecting sat calcuation -- seems weak, - // but actually, photoshop seems that way, too - float max; - float min = Math.min(Math.min(r,g), b); - if (r >= b) - { - if (r >= g) - { - max = r; // perhaps r==b or r==g - isMax = 0; - } - else // perhaps r==b; g is true max - { - max = g; - isMax = 1; - } - } - else - { - if (g >= b) - { - max = g; // perhaps g==b - isMax = 1; - } - else - { - max = b; // b is true max - isMax = 2; - } - } - - float delta = max - min; - - // calculate saturation - if (max == 0) - s = 0; - else - s = delta / max; // (s == 0) also if delta = 0 - - // calculate hue - if (s == 0) - h = (float) Math.random(); // hue is undefined when sat == 0 - else - { - // red = 0 yellow = 60 (1) green = 120 (2) - // cyan= 180 (3) blue = 240 (4) magenta = 300 (5) - // scale of 0 to 6, intitally - switch (isMax) - { - case 0: // red is max - if (r == b) - h = 5; // pure magenta - else if (r == g) - h = 1; // pure yellow - else - h = (g-b) / delta; // between yellow & magenta - break; - case 1: // green is max - if (g == b) - h = 3; // pure cyan - else - h = 2 + (b-r) / delta; // between cyan & yellow - break; - default: // case 2: blue is max - h = 4 + (r-g) / delta; // between magenta & cyan - } - h = h * 60; - if (h < 0) - h += 360; - h = h / 360; - - } - float hsv[] = {h, s, max}; - -// System.out.println("myHsv("+r+","+g+","+b+")="+ -// hsv[0]+","+hsv[1]+","+hsv[2]); - return hsv; - } - public static float hue(Color c) { return myHsv(c)[0]; } - public static float sat(Color c) { return myHsv(c)[1]; } - public static float value(Color c) { return myHsv(c)[2]; } - - public static Color value(Color c, float newValue) - { - float hsv[] = myHsv(c); - return Color.getHSBColor(hsv[0], hsv[1], newValue); - } - public static Color nearby(Color c, int HSorB, float factor) - { - float hsb[] = new float[3], changer; - // ??? could perhaps make it smaller w shifts and && - Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), hsb); -// System.out.println("Palette.nearby() " + hsb); - changer = (hsb[HSorB] + MathTools.pM(MathTools.randGain(.35f), factor) - + 1.0f) - % 1.0f; - hsb[HSorB] = changer; - return Color.getHSBColor(hsb[0], hsb[1], hsb[2]); - } - - public static Color hsb(float hue, float saturation, float brightness) - { return new Color(Color.HSBtoRGB(hue, saturation, brightness)); } - - static public Color hexToColor(String s) - { - Color result = Color.white; - boolean change = false; - for (int i=0; i!=colors.length; i++) - if (s.equalsIgnoreCase(colorNames[i])) - { - result = colors[i]; - change = true; - break; - } - if (!change) - { - int j = s.indexOf("#") + 1; - if (j > -1) - { - s = s.substring(j); - result = new Color(Integer.parseInt(s,16)); - } - } - return result; - } - - - - -// { return Color.getHSBColor(hue, saturation, brightness); } - - -} +/* + * Copyright 1996-2002 by Andruid Kerne. All rights reserved. + * CONFIDENTIAL. Use is subject to license terms. + */ +package ecologylab.generic; + +import java.awt.Color; + +/** + * Tools for manipulating color spaces. + */ +public class Palette +extends Debug +{ + static float delta = .085f; + + static final String colorNames[] = + { + "blue", "black", "cyan", "darkGray", "gray", + "green", "lightGray", "magenta", "orange", + "pink", "red", "white", "yellow", + }; + + + static final Color colors[] = + { + Color.blue, Color.black, Color.cyan, Color.darkGray, Color.gray, + Color.green, Color.lightGray, Color.magenta, Color.orange, + Color.pink, Color.red, Color.white, Color.yellow, + }; + + + Palette(){} + + // generate complementary color + public static int Complement(Color c) + { + float hsb[] = new float[3]; + Color.RGBtoHSB (c.getRed(), c.getGreen(), c.getBlue(), hsb); + hsb[0] += .5f; + if (hsb[0] > 1) + hsb[0] -= 1; + return Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]); + } + + public static Color complement(Color c) + { + return new Color(Complement(c)); + } + // return 2 colors delta away from the input + public static void Split(Color input, int[] output) + { + float hsb[] = new float[3]; + float newHue; + Color.RGBtoHSB (input.getRed(), input.getGreen(), input.getBlue(), + hsb); + newHue = (hsb[0] + delta) % 1.0f; + output[0] = Color.HSBtoRGB(newHue, hsb[1], hsb[2]); + newHue = (hsb[0] - delta) % 1.0f; + output[1] = Color.HSBtoRGB(newHue, hsb[1], hsb[2]); + } + + public static Color hsvColor(float h, float s, float v) + { + int rgb[] = rgb(h,s,v); + Color result = new Color(rgb[0], rgb[1], rgb[2]); + //println("Palette.hsvColor("+h+","+s+","+v+") = " + result); + return result; + } + + // hsv to rgb + public static int[] rgb(float hf, float s, float v) + { + float r=0,g=0,b=0; + float h = hf * 6; + if (s == 0) + { + r = v; + g = v; + b = v; + } + else + { + int i = (int) Math.floor(h); + float f = h - i; + float p = v * (1 - s); + float q = v * (1 - s*f); + float t = v * (1 - s*(1-f)); + switch (i) + { + case 0: + r = v; + g = t; + b = p; + break; + case 1: + r = q; + g = v; + b = p; + break; + case 2: + r = p; + g = v; + b = t; + break; + case 3: + r = p; + g = q; + b = v; + break; + case 4: + r = t; + g = p; + b = v; + break; + case 5: + r = v; + g = p; + b = q; + break; + } + } + int rgb[] = new int[3]; + rgb[0] = (int) (r * 255); + rgb[1] = (int) (g * 255); + rgb[2] = (int) (b * 255); +// System.out.println("rgb( " +hf+","+s+","+v+" => "+ +// rgb[0]+","+rgb[1]+","+rgb[2]); + return rgb; + } + + // hsv to rgb + public static void rgb(float hf, float s, float v, float[] result) + { + float r=0,g=0,b=0; + float h = hf * 6; + if (s == 0) + { + r = v; + g = v; + b = v; + } + else + { + int i = (int) Math.floor(h); + float f = h - i; + float p = v * (1 - s); + float q = v * (1 - s*f); + float t = v * (1 - s*(1-f)); + switch (i) + { + case 0: + r = v; + g = t; + b = p; + break; + case 1: + r = q; + g = v; + b = p; + break; + case 2: + r = p; + g = v; + b = t; + break; + case 3: + r = p; + g = q; + b = v; + break; + case 4: + r = t; + g = p; + b = v; + break; + case 5: + r = v; + g = p; + b = q; + break; + } + } + result[0] = r; + result[1] = g; + result[2] = b; + } + + // from rgb to hsv + public static float[] hsv(Color c) + { + // note that when saturation=0, hue is undefined (we'll set to 0) + float hsv[] = new float[3]; + Color.RGBtoHSB (c.getRed(), c.getGreen(), c.getBlue(), hsv); + float f = Math.min(hsv[1],.999f); + hsv[1] = f; + f = Math.min(hsv[2],.999f); + hsv[2] = f; + +// System.out.println("hsv("+c+")="+hsv[0]+","+hsv[1]+","+hsv[2]); + return hsv; + } + + public static float[] myHsv(Color c) + { + return myHsv(c.getRed(), c.getGreen(), c.getBlue()); + } + + public static float[] myHsv(int ri, int gi, int bi) + { + float r = ((float) ri) / 255, + g = ((float) gi) / 255, + b = ((float) bi) / 255; + + float h, s; + int isMax; // 0 red, 1 green, 2 blue + // nb: ties don't effect value calculation + // ties here don't effect hue calculation due to code below + // ties aren't effecting sat calcuation -- seems weak, + // but actually, photoshop seems that way, too + float max; + float min = Math.min(Math.min(r,g), b); + if (r >= b) + { + if (r >= g) + { + max = r; // perhaps r==b or r==g + isMax = 0; + } + else // perhaps r==b; g is true max + { + max = g; + isMax = 1; + } + } + else + { + if (g >= b) + { + max = g; // perhaps g==b + isMax = 1; + } + else + { + max = b; // b is true max + isMax = 2; + } + } + + float delta = max - min; + + // calculate saturation + if (max == 0) + s = 0; + else + s = delta / max; // (s == 0) also if delta = 0 + + // calculate hue + if (s == 0) + h = (float) Math.random(); // hue is undefined when sat == 0 + else + { + // red = 0 yellow = 60 (1) green = 120 (2) + // cyan= 180 (3) blue = 240 (4) magenta = 300 (5) + // scale of 0 to 6, intitally + switch (isMax) + { + case 0: // red is max + if (r == b) + h = 5; // pure magenta + else if (r == g) + h = 1; // pure yellow + else + h = (g-b) / delta; // between yellow & magenta + break; + case 1: // green is max + if (g == b) + h = 3; // pure cyan + else + h = 2 + (b-r) / delta; // between cyan & yellow + break; + default: // case 2: blue is max + h = 4 + (r-g) / delta; // between magenta & cyan + } + h = h * 60; + if (h < 0) + h += 360; + h = h / 360; + + } + float hsv[] = {h, s, max}; + +// System.out.println("myHsv("+r+","+g+","+b+")="+ +// hsv[0]+","+hsv[1]+","+hsv[2]); + return hsv; + } + public static float hue(Color c) { return myHsv(c)[0]; } + public static float sat(Color c) { return myHsv(c)[1]; } + public static float value(Color c) { return myHsv(c)[2]; } + + public static Color value(Color c, float newValue) + { + float hsv[] = myHsv(c); + return Color.getHSBColor(hsv[0], hsv[1], newValue); + } + public static Color nearby(Color c, int HSorB, float factor) + { + float hsb[] = new float[3], changer; + // ??? could perhaps make it smaller w shifts and && + Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), hsb); +// System.out.println("Palette.nearby() " + hsb); + changer = (hsb[HSorB] + MathTools.pM(MathTools.randGain(.35f), factor) + + 1.0f) + % 1.0f; + hsb[HSorB] = changer; + return Color.getHSBColor(hsb[0], hsb[1], hsb[2]); + } + + public static Color hsb(float hue, float saturation, float brightness) + { return new Color(Color.HSBtoRGB(hue, saturation, brightness)); } + + static public Color hexToColor(String s) + { + Color result = Color.white; + boolean change = false; + for (int i=0; i!=colors.length; i++) + if (s.equalsIgnoreCase(colorNames[i])) + { + result = colors[i]; + change = true; + break; + } + if (!change) + { + int j = s.indexOf("#") + 1; + if (j > -1) + { + s = s.substring(j); + result = new Color(Integer.parseInt(s,16)); + } + } + return result; + } + + + + +// { return Color.getHSBColor(hue, saturation, brightness); } + + +} diff --git a/simplCore/src/ecologylab/generic/ReflectionTools.java b/simplCore/src/ecologylab/generic/ReflectionTools.java index 596e1cd8..62da37e1 100644 --- a/simplCore/src/ecologylab/generic/ReflectionTools.java +++ b/simplCore/src/ecologylab/generic/ReflectionTools.java @@ -1,306 +1,306 @@ -package ecologylab.generic; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; - -/** - * Utility routines for working with reflection. - * - * @author andruid - */ -public class ReflectionTools extends Debug -{ - -/** - * Get the Field object with name fieldName, in thatClass. - * - * @param thatClass - * @param fieldName - * - * @return The Field object in thatClass, or null if there is none accessible. - */ - public static Field getField(Class thatClass, String fieldName) - { - Field result = null; - try - { - result = thatClass.getField(fieldName); - } catch (SecurityException e) - { - } catch (NoSuchFieldException e) - { - } - return result; - } - - /** - * Get the Field object with name fieldName, in thatClass. - * - * @param thatClass - * @param fieldName - * - * @return The Field object in thatClass, or null if there is none accessible. - */ - public static Field getDeclaredField(Class thatClass, String fieldName) - { - Field result = null; - try - { - result = thatClass.getDeclaredField(fieldName); - } catch (SecurityException e) - { - } catch (NoSuchFieldException e) - { - } - return result; - } - public static final Object BAD_ACCESS = new Object(); - - /** - * Return the value of the Field in the Object, or BAD_ACCESS if it can't be accessed. - * - * @param that - * @param field - * @return - */ - public static Object getFieldValue(Object that, Field field) - { - Object result = null; - try - { - result = field.get(that); - } catch (IllegalArgumentException e) - { - result = BAD_ACCESS; - e.printStackTrace(); - } catch (IllegalAccessException e) - { - result = BAD_ACCESS; - e.printStackTrace(); - } - return result; - } - - /** - * Set a reference type Field to a value. - * - * @param that Object that the field is in. - * @param field Reference type field within that object. - * @param value Value to set the reference field to. - * - * @return true if the set succeeds. - */ - public static boolean setFieldValue(Object that, Field field, Object value) - { - boolean result = false; - try - { - field.set(that, value); - result = true; - } catch (IllegalArgumentException e) - { - e.printStackTrace(); - } catch (IllegalAccessException e) - { - e.printStackTrace(); - } - return true; - } -/** - * Wraps the no argument getInstance() method. - * Checks to see if the class object passed in is null, or if - * any exceptions are thrown by newInstance(). - * - * @param thatClass - * @return An instance of an object of the specified class, or null if the Class object was null or - * an InstantiationException or IllegalAccessException was thrown in the attempt to instantiate. - */ - public static T getInstance(Class thatClass) - { - T result = null; - if (thatClass != null) - { - try - { - result = thatClass.newInstance(); - } catch (InstantiationException e) - { - e.printStackTrace(); - } catch (IllegalAccessException e) - { - e.printStackTrace(); - } - } - return result; - } - - /** - * Wraps the no argument getInstance() method. - * Checks to see if the class object passed in is null, or if - * any exceptions are thrown by newInstance(). - * - * @param thatClass - * @return An instance of an object of the specified class, or null if the Class object was null or - * an InstantiationException or IllegalAccessException was thrown in the attempt to instantiate. - */ - public static T getInstance(Class thatClass, Class[] parameterTypes, Object[] args) - { - T result = null; - if (thatClass != null) - { - try - { - Constructor constructor = thatClass.getDeclaredConstructor(parameterTypes); - if (constructor != null) - result = constructor.newInstance(args); - - } catch (SecurityException e1) - { - e1.printStackTrace(); - } catch (NoSuchMethodException e1) - { - e1.printStackTrace(); - println(thatClass.getName() + " | ReflectionTools.getInstance() NoSuchMethodException: getDeclaredConstructor"); - } catch (IllegalArgumentException e) - { - e.printStackTrace(); - } catch (InstantiationException e) - { - e.printStackTrace(); - } catch (IllegalAccessException e) - { - e.printStackTrace(); - } catch (InvocationTargetException e) - { - Throwable cause = e.getCause(); - cause.printStackTrace(); - e.printStackTrace(); - } - } - return result; - } - - /** - * Find a Method object if there is one in the context class, or return null if not. - * - * @param context Class to find the Method in. - * @param name Name of the method. - * @param types Array of Class objects indicating parameter types. - * - * @return The associated Method object, or null if non is accessible. - */ - public static Method getMethod(Class context, String name, Class[] types) - { - Method result = null; - try - { - result = context.getMethod(name, types); - } catch (SecurityException e) - { - } catch (NoSuchMethodException e) - { - } - return result; - } - /** - * See if the Field has the annotation in its declaration. - * - * @param field - * @param annotationClass - * @return - */ - public static boolean isAnnotationPresent(Field field, Class annotationClass) - { - return field.isAnnotationPresent(annotationClass); - } - - /** - * Get the parameterized type tokens that the generic Field was declared with. - * - * @param reflectType - * @return - */ - public static Type[] getParameterizedTypeTokens(Field field) - { - Type reflectType = field.getGenericType(); - return getParameterizedTypeTokens(reflectType); - } - - private static Type[] getParameterizedTypeTokens(Type reflectType) - { - Type[] result = null; - if (reflectType instanceof ParameterizedType) - { - ParameterizedType pType = (ParameterizedType) reflectType; - result = pType.getActualTypeArguments(); - } - else if (reflectType instanceof Class) - { - Type superType = ((Class) reflectType).getGenericSuperclass(); - return getParameterizedTypeTokens(superType); - } - return result; - } - /** - * Invoke a method with return type void and a single argument. - * - * @param method - * @param arg - */ - public static void invoke(Method method, Object context, Object arg) - { - Object[] args = {arg}; - try - { - method.invoke(context, args); - } - catch (IllegalArgumentException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - catch (IllegalAccessException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - catch (InvocationTargetException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - public static void copyObject(final Object source,Object destination) - // get the metadata class - { - Class cls = source.getClass(); - - // get all the fields of that class - Field[] fields = cls.getDeclaredFields(); - - // iterate over that field - for(int i=0;i T getInstance(Class thatClass) + { + T result = null; + if (thatClass != null) + { + try + { + result = thatClass.newInstance(); + } catch (InstantiationException e) + { + e.printStackTrace(); + } catch (IllegalAccessException e) + { + e.printStackTrace(); + } + } + return result; + } + + /** + * Wraps the no argument getInstance() method. + * Checks to see if the class object passed in is null, or if + * any exceptions are thrown by newInstance(). + * + * @param thatClass + * @return An instance of an object of the specified class, or null if the Class object was null or + * an InstantiationException or IllegalAccessException was thrown in the attempt to instantiate. + */ + public static T getInstance(Class thatClass, Class[] parameterTypes, Object[] args) + { + T result = null; + if (thatClass != null) + { + try + { + Constructor constructor = thatClass.getDeclaredConstructor(parameterTypes); + if (constructor != null) + result = constructor.newInstance(args); + + } catch (SecurityException e1) + { + e1.printStackTrace(); + } catch (NoSuchMethodException e1) + { + e1.printStackTrace(); + println(thatClass.getName() + " | ReflectionTools.getInstance() NoSuchMethodException: getDeclaredConstructor"); + } catch (IllegalArgumentException e) + { + e.printStackTrace(); + } catch (InstantiationException e) + { + e.printStackTrace(); + } catch (IllegalAccessException e) + { + e.printStackTrace(); + } catch (InvocationTargetException e) + { + Throwable cause = e.getCause(); + cause.printStackTrace(); + e.printStackTrace(); + } + } + return result; + } + + /** + * Find a Method object if there is one in the context class, or return null if not. + * + * @param context Class to find the Method in. + * @param name Name of the method. + * @param types Array of Class objects indicating parameter types. + * + * @return The associated Method object, or null if non is accessible. + */ + public static Method getMethod(Class context, String name, Class[] types) + { + Method result = null; + try + { + result = context.getMethod(name, types); + } catch (SecurityException e) + { + } catch (NoSuchMethodException e) + { + } + return result; + } + /** + * See if the Field has the annotation in its declaration. + * + * @param field + * @param annotationClass + * @return + */ + public static boolean isAnnotationPresent(Field field, Class annotationClass) + { + return field.isAnnotationPresent(annotationClass); + } + + /** + * Get the parameterized type tokens that the generic Field was declared with. + * + * @param reflectType + * @return + */ + public static Type[] getParameterizedTypeTokens(Field field) + { + Type reflectType = field.getGenericType(); + return getParameterizedTypeTokens(reflectType); + } + + private static Type[] getParameterizedTypeTokens(Type reflectType) + { + Type[] result = null; + if (reflectType instanceof ParameterizedType) + { + ParameterizedType pType = (ParameterizedType) reflectType; + result = pType.getActualTypeArguments(); + } + else if (reflectType instanceof Class) + { + Type superType = ((Class) reflectType).getGenericSuperclass(); + return getParameterizedTypeTokens(superType); + } + return result; + } + /** + * Invoke a method with return type void and a single argument. + * + * @param method + * @param arg + */ + public static void invoke(Method method, Object context, Object arg) + { + Object[] args = {arg}; + try + { + method.invoke(context, args); + } + catch (IllegalArgumentException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + catch (IllegalAccessException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + catch (InvocationTargetException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public static void copyObject(final Object source,Object destination) + // get the metadata class + { + Class cls = source.getClass(); + + // get all the fields of that class + Field[] fields = cls.getDeclaredFields(); + + // iterate over that field + for(int i=0;i extends Debug -{ - protected static final int DEFAULT_POOL_SIZE = 16; - - public static final int NEVER_CONTRACT = -1; - - private final ArrayList pool; - - /** - * The number of resources this pool is currently in control of, including the number of resources - * that are currently acquired by other processes. - */ - private int capacity; - - /** - * Specifies the minimum size for the backing store, to prevent thrashing when small numbers of - * objects are needed. - */ - private final int minCapacity; - - private final float loadFactor = .75f; - - /** - * If true, stores the hash of each resource that is released to this pool and throws an exception - * if a resource is released more than once. - */ - private boolean checkMultiRelease; - - /** - * Stores a listing of the hashes of all of the resources currently held by the resource pool. - * This field is only instantiated if checkMultiRelease is true, if it is false, this field will - * be NULL. - */ - private final HashSet releasedResourceHashes; - - /** - * Special constructor that will only instantiate the backing pool resources if the first argument - * is true. This method can be used by subclasses to set up member variables before calling - * instantiateResourcesInPool(), so that the instantiation will use the member variables. - * - * @param instantiateResourcesInPool - * @param initialPoolSize - * @param minimumPoolSize - * the size of the pool will never contract below this value. If NEVER_CONTRACT is - * passed, the pool will never contract. - */ - protected ResourcePool( boolean instantiateResourcesInPool, - int initialPoolSize, - int minimumPoolSize, - boolean checkMultiRelease) - { - this.capacity = Math.max(initialPoolSize, minimumPoolSize); - - this.pool = new ArrayList(capacity); - - if (checkMultiRelease) - releasedResourceHashes = new HashSet(); - else - releasedResourceHashes = null; - - if (instantiateResourcesInPool) - instantiateResourcesInPool(); - - this.minCapacity = minimumPoolSize; - this.checkMultiRelease = checkMultiRelease; - } - - /** - * Creates a new ResourcePool with the specified initialPoolSize (or minimumPoolSize, - * minimumPoolSize > initialPoolSize) and minimum capacity. - * - * Note that this constructor will call generateNewResource (capacity) times to fill in the - * backing collection. If generateNewResource relies upon setting fields, the subclass should - * *NOT* call this constructor and should instead call ResourcePool(boolean, int, int). - * - * @param initialPoolSize - * the initial size of the backing pool of objects. - * @param minimumPoolSize - * the minimum size for the backing pool of objects. This is important to specify, - * otherwise repeatedly aquire()'ing and release()'ing resources can negatively affect - * performance. - */ - protected ResourcePool(int initialPoolSize, int minimumPoolSize) - { - this(true, initialPoolSize, minimumPoolSize, false); - } - - /** - * Releases all objects owned by this pool. - */ - protected synchronized void shutdown() - { - int size = this.pool.size(); - - for (int i = size - 1; i >= 0; i--) - { - onRemoval(this.remove(i)); - } - } - - protected void onAcquire() - { - - } - - /** - * Take a resource from the pool, making it unavailable for other segments of the program to use. - * - * Objects returned by calls to acquire() are "clean", that is, they are in the same state they - * would be in as if they were just instantiated. - * - * @return - */ - public final T acquire() - { - T retVal; - - int freeIndex; - - synchronized (this) - { // when acquire()'ing it might be necessary to expand the size of the - // backing store - onAcquire(); - - freeIndex = this.pool.size() - 1; - - if (freeIndex == -1) - { - this.expandPool(); - freeIndex = this.pool.size() - 1; - } - - retVal = this.remove(freeIndex); - } - - this.clean(retVal); - - return retVal; - } - - protected void onRelease(T resourceToRelease) - { - - } - - /** - * Return a resource for use by another part of the program. The resource will be cleaned at some - * later time when it is acquire()'ed. Resources that are released should NOT be used again. - * - * @param resourceToRelease - * @return null; this is meant as a convenience, so that the programmer can use the line: resource - * = recPool.release(resource);, automatically unlinking the released resource from the - * binding in the resource user's code. - */ - public final synchronized T release(T resourceToRelease) - { - if (resourceToRelease != null) - { - synchronized (this) - { - if (!this.add(resourceToRelease)) - return null; - - int poolSize = pool.size(); - - if (minCapacity != NEVER_CONTRACT && capacity > minCapacity - && poolSize > loadFactor * capacity) - { - this.contractPool(); - } - onRelease(resourceToRelease); - } - - } - else - { - warning("attempt to load a null reference into resource pool."); - } - - return null; - } - - /** - * Instantiates a resource of type T. - * - * @return - */ - protected abstract T generateNewResource(); - - /** - * Ensure that the given Object is "clean", that is, in the state it would be in if it were just - * instantiated. For example, if this class were handling StringBuilders, it should ensure that - * the StringBuilder does not contain any characters from a previous use. - * - * clean(T) is automatically called immediately before an object is returned from the acquire() - * method. - * - * @param objectToClean - */ - protected abstract void clean(T objectToClean); - - /** - * Increases the number of resources to make available. Doubles the backing Collection size and - * instantiates objects to match. - * - * expandPool() is not thread-safe and should only be called within a synchronized block. - */ - private void expandPool() - { - int oldCap = capacity; - - if (capacity > 0) - { - /* - * double capacity by instantiating new objects; this doubles, b/c when this method - * is called, we are empty and have already dealt-out objects - */ - instantiateResourcesInPool(); - - capacity *= 2; - } - else - { // capacity is 0, just put one in there - this.add(this.generateNewResource()); - capacity = 1; - } - - debug("expanding pool from " + oldCap + " elements to " + capacity + " elements"); - - this.pool.ensureCapacity(capacity); - } - - private void contractPool() - { - int oldCap = capacity; - capacity /= 2; - - for (int i = 0; (i < capacity && pool.size() > minCapacity); i++) - onRemoval(this.remove(pool.size() - 1)); - - if (capacity < minCapacity) - { - capacity = minCapacity; - } - - // this is kludge, but it can't be done any other with with ArrayList. - // Both of these cost an arrayCopy(), but the - // alternative is to end up with an arrayCopy on each subsequent add(). - pool.trimToSize(); - pool.ensureCapacity(capacity); - - debug("contracting pool from " + oldCap + " elements to " + capacity + " elements"); - } - - /** - * Lets a subclass control what happens to the object when it is thrown away, letting the - * developer release any resources they may have allocated. - * - * onRemoval(T) is called when the object is about to removed during a contraction - * - * @param remove - */ - protected void onRemoval(T remove) - { - - } - - /** - * - */ - protected void instantiateResourcesInPool() - { - for (int i = 0; i < capacity; i++) - this.add(this.generateNewResource()); - } - - /** - * Removes a resource from the pool to be either returned or recycled. Handles housekeeping with - * the hashes if necessary. - * - * @param index - * @return - */ - private T remove(int index) - { - T removedResource = pool.remove(index); - - if (this.checkMultiRelease) - this.releasedResourceHashes.remove(removedResource); - - return removedResource; - } - - /** - * Adds a resource to the pool. Handles housekeeping with hashes if necessary. - * - * @param resource - */ - private boolean add(T resource) - { - if (this.checkMultiRelease && !this.releasedResourceHashes.add(resource)) - throw new RuntimeException("Attempted to release the same resource more than once: " - + resource.toString()); - - pool.add(resource); - - return true; - } - - /** - * @return the capacity - */ - public int getCapacity() - { - return capacity; - } - - public int getPoolSize() - { - return this.pool.size(); - } +/* + * Created on Nov 19, 2007 + */ +package ecologylab.generic; + +import java.util.ArrayList; +import java.util.HashSet; + +/** + * This class provides access to a pool of pre-allocated resources. The pool grows and contracts + * throughout its lifetime to suit the number of resources necessary and to attempt to minimize + * memory footprints; acquire() and release() are amortized O(1) complexity (although + * expansion/contraction triggers may take longer). + * + * The primary way of accessing resources that are controlled by a pool are through the acquire and + * release methods. Every acquire should have a matching release, to ensure that resources may be + * recycled by later calls to acquire. + * + * Subclasses of ResourcePool ensure that the resources obtained through the acquire method are + * "clean", that is, they are immediately ready for use as if they were just instantiated. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public abstract class ResourcePool extends Debug +{ + protected static final int DEFAULT_POOL_SIZE = 16; + + public static final int NEVER_CONTRACT = -1; + + private final ArrayList pool; + + /** + * The number of resources this pool is currently in control of, including the number of resources + * that are currently acquired by other processes. + */ + private int capacity; + + /** + * Specifies the minimum size for the backing store, to prevent thrashing when small numbers of + * objects are needed. + */ + private final int minCapacity; + + private final float loadFactor = .75f; + + /** + * If true, stores the hash of each resource that is released to this pool and throws an exception + * if a resource is released more than once. + */ + private boolean checkMultiRelease; + + /** + * Stores a listing of the hashes of all of the resources currently held by the resource pool. + * This field is only instantiated if checkMultiRelease is true, if it is false, this field will + * be NULL. + */ + private final HashSet releasedResourceHashes; + + /** + * Special constructor that will only instantiate the backing pool resources if the first argument + * is true. This method can be used by subclasses to set up member variables before calling + * instantiateResourcesInPool(), so that the instantiation will use the member variables. + * + * @param instantiateResourcesInPool + * @param initialPoolSize + * @param minimumPoolSize + * the size of the pool will never contract below this value. If NEVER_CONTRACT is + * passed, the pool will never contract. + */ + protected ResourcePool( boolean instantiateResourcesInPool, + int initialPoolSize, + int minimumPoolSize, + boolean checkMultiRelease) + { + this.capacity = Math.max(initialPoolSize, minimumPoolSize); + + this.pool = new ArrayList(capacity); + + if (checkMultiRelease) + releasedResourceHashes = new HashSet(); + else + releasedResourceHashes = null; + + if (instantiateResourcesInPool) + instantiateResourcesInPool(); + + this.minCapacity = minimumPoolSize; + this.checkMultiRelease = checkMultiRelease; + } + + /** + * Creates a new ResourcePool with the specified initialPoolSize (or minimumPoolSize, + * minimumPoolSize > initialPoolSize) and minimum capacity. + * + * Note that this constructor will call generateNewResource (capacity) times to fill in the + * backing collection. If generateNewResource relies upon setting fields, the subclass should + * *NOT* call this constructor and should instead call ResourcePool(boolean, int, int). + * + * @param initialPoolSize + * the initial size of the backing pool of objects. + * @param minimumPoolSize + * the minimum size for the backing pool of objects. This is important to specify, + * otherwise repeatedly aquire()'ing and release()'ing resources can negatively affect + * performance. + */ + protected ResourcePool(int initialPoolSize, int minimumPoolSize) + { + this(true, initialPoolSize, minimumPoolSize, false); + } + + /** + * Releases all objects owned by this pool. + */ + protected synchronized void shutdown() + { + int size = this.pool.size(); + + for (int i = size - 1; i >= 0; i--) + { + onRemoval(this.remove(i)); + } + } + + protected void onAcquire() + { + + } + + /** + * Take a resource from the pool, making it unavailable for other segments of the program to use. + * + * Objects returned by calls to acquire() are "clean", that is, they are in the same state they + * would be in as if they were just instantiated. + * + * @return + */ + public final T acquire() + { + T retVal; + + int freeIndex; + + synchronized (this) + { // when acquire()'ing it might be necessary to expand the size of the + // backing store + onAcquire(); + + freeIndex = this.pool.size() - 1; + + if (freeIndex == -1) + { + this.expandPool(); + freeIndex = this.pool.size() - 1; + } + + retVal = this.remove(freeIndex); + } + + this.clean(retVal); + + return retVal; + } + + protected void onRelease(T resourceToRelease) + { + + } + + /** + * Return a resource for use by another part of the program. The resource will be cleaned at some + * later time when it is acquire()'ed. Resources that are released should NOT be used again. + * + * @param resourceToRelease + * @return null; this is meant as a convenience, so that the programmer can use the line: resource + * = recPool.release(resource);, automatically unlinking the released resource from the + * binding in the resource user's code. + */ + public final synchronized T release(T resourceToRelease) + { + if (resourceToRelease != null) + { + synchronized (this) + { + if (!this.add(resourceToRelease)) + return null; + + int poolSize = pool.size(); + + if (minCapacity != NEVER_CONTRACT && capacity > minCapacity + && poolSize > loadFactor * capacity) + { + this.contractPool(); + } + onRelease(resourceToRelease); + } + + } + else + { + warning("attempt to load a null reference into resource pool."); + } + + return null; + } + + /** + * Instantiates a resource of type T. + * + * @return + */ + protected abstract T generateNewResource(); + + /** + * Ensure that the given Object is "clean", that is, in the state it would be in if it were just + * instantiated. For example, if this class were handling StringBuilders, it should ensure that + * the StringBuilder does not contain any characters from a previous use. + * + * clean(T) is automatically called immediately before an object is returned from the acquire() + * method. + * + * @param objectToClean + */ + protected abstract void clean(T objectToClean); + + /** + * Increases the number of resources to make available. Doubles the backing Collection size and + * instantiates objects to match. + * + * expandPool() is not thread-safe and should only be called within a synchronized block. + */ + private void expandPool() + { + int oldCap = capacity; + + if (capacity > 0) + { + /* + * double capacity by instantiating new objects; this doubles, b/c when this method + * is called, we are empty and have already dealt-out objects + */ + instantiateResourcesInPool(); + + capacity *= 2; + } + else + { // capacity is 0, just put one in there + this.add(this.generateNewResource()); + capacity = 1; + } + + debug("expanding pool from " + oldCap + " elements to " + capacity + " elements"); + + this.pool.ensureCapacity(capacity); + } + + private void contractPool() + { + int oldCap = capacity; + capacity /= 2; + + for (int i = 0; (i < capacity && pool.size() > minCapacity); i++) + onRemoval(this.remove(pool.size() - 1)); + + if (capacity < minCapacity) + { + capacity = minCapacity; + } + + // this is kludge, but it can't be done any other with with ArrayList. + // Both of these cost an arrayCopy(), but the + // alternative is to end up with an arrayCopy on each subsequent add(). + pool.trimToSize(); + pool.ensureCapacity(capacity); + + debug("contracting pool from " + oldCap + " elements to " + capacity + " elements"); + } + + /** + * Lets a subclass control what happens to the object when it is thrown away, letting the + * developer release any resources they may have allocated. + * + * onRemoval(T) is called when the object is about to removed during a contraction + * + * @param remove + */ + protected void onRemoval(T remove) + { + + } + + /** + * + */ + protected void instantiateResourcesInPool() + { + for (int i = 0; i < capacity; i++) + this.add(this.generateNewResource()); + } + + /** + * Removes a resource from the pool to be either returned or recycled. Handles housekeeping with + * the hashes if necessary. + * + * @param index + * @return + */ + private T remove(int index) + { + T removedResource = pool.remove(index); + + if (this.checkMultiRelease) + this.releasedResourceHashes.remove(removedResource); + + return removedResource; + } + + /** + * Adds a resource to the pool. Handles housekeeping with hashes if necessary. + * + * @param resource + */ + private boolean add(T resource) + { + if (this.checkMultiRelease && !this.releasedResourceHashes.add(resource)) + throw new RuntimeException("Attempted to release the same resource more than once: " + + resource.toString()); + + pool.add(resource); + + return true; + } + + /** + * @return the capacity + */ + public int getCapacity() + { + return capacity; + } + + public int getPoolSize() + { + return this.pool.size(); + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/generic/ResourcePoolWithSize.java b/simplCore/src/ecologylab/generic/ResourcePoolWithSize.java index 4835d6e3..446676d7 100644 --- a/simplCore/src/ecologylab/generic/ResourcePoolWithSize.java +++ b/simplCore/src/ecologylab/generic/ResourcePoolWithSize.java @@ -1,47 +1,47 @@ -/** - * - */ -package ecologylab.generic; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public abstract class ResourcePoolWithSize extends ResourcePool -{ - protected int resourceObjectCapacity; - - /** - * @param initialPoolSize - * @param minimumPoolSize - * @param resourceObjectCapacity - * the capacity of objects that are contained in this pool; for example, if this is a - * ResourcePoolWithSize\, this would specify the size of the - * StringBuilders in the pool. - */ - public ResourcePoolWithSize(int initialPoolSize, int minimumPoolSize, int resourceObjectCapacity) - { - super(false, initialPoolSize, minimumPoolSize, false); - - this.resourceObjectCapacity = resourceObjectCapacity; - - this.instantiateResourcesInPool(); - } - - /** - * @param initialPoolSize - * @param minimumPoolSize - * @param resourceObjectCapacity - * the capacity of objects that are contained in this pool; for example, if this is a - * ResourcePoolWithSize\, this would specify the size of the - * StringBuilders in the pool. - */ - public ResourcePoolWithSize(int initialPoolSize, int minimumPoolSize, int resourceObjectCapacity, boolean checkMultiRelease) - { - super(false, initialPoolSize, minimumPoolSize, checkMultiRelease); - - this.resourceObjectCapacity = resourceObjectCapacity; - - this.instantiateResourcesInPool(); - } -} +/** + * + */ +package ecologylab.generic; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public abstract class ResourcePoolWithSize extends ResourcePool +{ + protected int resourceObjectCapacity; + + /** + * @param initialPoolSize + * @param minimumPoolSize + * @param resourceObjectCapacity + * the capacity of objects that are contained in this pool; for example, if this is a + * ResourcePoolWithSize\, this would specify the size of the + * StringBuilders in the pool. + */ + public ResourcePoolWithSize(int initialPoolSize, int minimumPoolSize, int resourceObjectCapacity) + { + super(false, initialPoolSize, minimumPoolSize, false); + + this.resourceObjectCapacity = resourceObjectCapacity; + + this.instantiateResourcesInPool(); + } + + /** + * @param initialPoolSize + * @param minimumPoolSize + * @param resourceObjectCapacity + * the capacity of objects that are contained in this pool; for example, if this is a + * ResourcePoolWithSize\, this would specify the size of the + * StringBuilders in the pool. + */ + public ResourcePoolWithSize(int initialPoolSize, int minimumPoolSize, int resourceObjectCapacity, boolean checkMultiRelease) + { + super(false, initialPoolSize, minimumPoolSize, checkMultiRelease); + + this.resourceObjectCapacity = resourceObjectCapacity; + + this.instantiateResourcesInPool(); + } +} diff --git a/simplCore/src/ecologylab/generic/ScaledValueObserver.java b/simplCore/src/ecologylab/generic/ScaledValueObserver.java index e8e2e6ea..c3796d80 100644 --- a/simplCore/src/ecologylab/generic/ScaledValueObserver.java +++ b/simplCore/src/ecologylab/generic/ScaledValueObserver.java @@ -1,16 +1,16 @@ -/* - * Created on Sep 28, 2005 - * - */ -package ecologylab.generic; - -import ecologylab.serialization.ElementObserver; - -/** - * @author Andrew Webb - * - */ -public interface ScaledValueObserver extends ElementObserver -{ - public short getScaledValue(); -} +/* + * Created on Sep 28, 2005 + * + */ +package ecologylab.generic; + +import ecologylab.serialization.ElementObserver; + +/** + * @author Andrew Webb + * + */ +public interface ScaledValueObserver extends ElementObserver +{ + public short getScaledValue(); +} diff --git a/simplCore/src/ecologylab/generic/StartAndStoppable.java b/simplCore/src/ecologylab/generic/StartAndStoppable.java index 0fe6c866..346f17a6 100644 --- a/simplCore/src/ecologylab/generic/StartAndStoppable.java +++ b/simplCore/src/ecologylab/generic/StartAndStoppable.java @@ -1,13 +1,13 @@ -package ecologylab.generic; - -/** - * A Runnable that, like most, can be start()ed and stop()ped. - * - * @author andruid - */ -public interface StartAndStoppable extends Runnable -{ - void start(); - - void stop(); -} +package ecologylab.generic; + +/** + * A Runnable that, like most, can be start()ed and stop()ped. + * + * @author andruid + */ +public interface StartAndStoppable extends Runnable +{ + void start(); + + void stop(); +} diff --git a/simplCore/src/ecologylab/generic/StringBuffersPool.java b/simplCore/src/ecologylab/generic/StringBuffersPool.java index de11b47c..27b5ca01 100644 --- a/simplCore/src/ecologylab/generic/StringBuffersPool.java +++ b/simplCore/src/ecologylab/generic/StringBuffersPool.java @@ -1,52 +1,52 @@ -package ecologylab.generic; - - -import java.util.Vector; - -/** - * A pool of reusable {@link java.lang.StringBuilder StringBuilder}s. - */ -@Deprecated public class StringBuffersPool -extends Debug -{ - public static int DEFAULT_POOL_SIZE = 64; - public Vector bufferPool; - - int bufferSize; - int poolSize; - - public StringBuffersPool(int bufferSize) - { - this(bufferSize, DEFAULT_POOL_SIZE); - } - public StringBuffersPool(int bufferSize, int poolSize) - { - this.bufferSize = bufferSize; - bufferPool = new Vector(poolSize); - for(int i = 0 ; i < poolSize; i++) - { - bufferPool.add(new StringBuilder(bufferSize)); - } - } - - public StringBuilder nextBuffer() - { - synchronized (bufferPool) - { - int freeIndex = bufferPool.size() - 1; - if (freeIndex == -1) - { - weird("extending pool size "); - return (new StringBuilder(bufferSize)); - } - StringBuilder b = bufferPool.remove(freeIndex); - return b; - } - } - - public void release(StringBuilder b) - { - b.setLength(0); - bufferPool.add(b); - } -} +package ecologylab.generic; + + +import java.util.Vector; + +/** + * A pool of reusable {@link java.lang.StringBuilder StringBuilder}s. + */ +@Deprecated public class StringBuffersPool +extends Debug +{ + public static int DEFAULT_POOL_SIZE = 64; + public Vector bufferPool; + + int bufferSize; + int poolSize; + + public StringBuffersPool(int bufferSize) + { + this(bufferSize, DEFAULT_POOL_SIZE); + } + public StringBuffersPool(int bufferSize, int poolSize) + { + this.bufferSize = bufferSize; + bufferPool = new Vector(poolSize); + for(int i = 0 ; i < poolSize; i++) + { + bufferPool.add(new StringBuilder(bufferSize)); + } + } + + public StringBuilder nextBuffer() + { + synchronized (bufferPool) + { + int freeIndex = bufferPool.size() - 1; + if (freeIndex == -1) + { + weird("extending pool size "); + return (new StringBuilder(bufferSize)); + } + StringBuilder b = bufferPool.remove(freeIndex); + return b; + } + } + + public void release(StringBuilder b) + { + b.setLength(0); + bufferPool.add(b); + } +} diff --git a/simplCore/src/ecologylab/generic/StringBuilderPool.java b/simplCore/src/ecologylab/generic/StringBuilderPool.java index e9fb6c52..aeb2f6f3 100644 --- a/simplCore/src/ecologylab/generic/StringBuilderPool.java +++ b/simplCore/src/ecologylab/generic/StringBuilderPool.java @@ -1,118 +1,118 @@ -/** - * - */ -package ecologylab.generic; - -/** - * ResourcePool for StringBuilders. - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class StringBuilderPool extends ResourcePoolWithSize -{ - /** - * - * @param builderSize - * the size of StringBuilders created within this pool. - */ - public StringBuilderPool(int builderSize) - { - this(DEFAULT_POOL_SIZE, NEVER_CONTRACT, builderSize); - } - - public StringBuilderPool(int poolSize, int builderSize) - { - this(poolSize, NEVER_CONTRACT, builderSize); - } - - /** - * @param poolSize - */ - public StringBuilderPool(int poolSize, int minimumCapacity, int builderSize) - { - this(poolSize, minimumCapacity, builderSize, false); - } - - public StringBuilderPool(int poolSize, int minimumCapacity, int builderSize, - boolean checkMultiRelease) - { - super(poolSize, minimumCapacity, builderSize, checkMultiRelease); - } - - /** - * Alias for acquire(). - * - * @return - */ - public StringBuilder nextBuffer() - { - return this.acquire(); - } - - /** - * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) - */ - @Override - protected void clean(StringBuilder objectToClean) - { - objectToClean.setLength(0); - } - - /** - * @see ecologylab.generic.ResourcePool#generateNewResource() - */ - @Override - protected StringBuilder generateNewResource() - { - return new StringBuilder(this.resourceObjectCapacity); - } - - public String releaseAndGetString(StringBuilder objectToRelease) - { - String s = StringTools.toString(objectToRelease); - this.release(objectToRelease); - return s; - } - - public static void main(String[] args) - { - - StringBuilderPool sbp = new StringBuilderPool(8, 2, 12, true); - System.out.println("0 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - - StringBuilder sb1 = new StringBuilder("asdf"); - StringBuilder sb2 = sb1; - StringBuilder sb3 = sb1; - - sbp.release(sb1); - System.out.println("1 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - sbp.release(sb2); - System.out.println("2 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - sbp.release(sb3); - System.out.println("3 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - - StringBuilder sb4 = sbp.acquire(); - System.out.println("4 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - StringBuilder sb5 = sb4; - - sbp.release(sb5); - System.out.println("5 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - sbp.release(sb4); - System.out.println("6 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - - StringBuilder sb6 = sbp.acquire(); - System.out.println("7 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - StringBuilder sb7 = sbp.acquire(); - System.out.println("8 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - StringBuilder sb8 = sbp.acquire(); - System.out.println("9 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - - sbp.release(sb6); - System.out.println("10 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - sbp.release(sb7); - System.out.println("11 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - sbp.release(sb8); - System.out.println("12 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); - } -} +/** + * + */ +package ecologylab.generic; + +/** + * ResourcePool for StringBuilders. + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class StringBuilderPool extends ResourcePoolWithSize +{ + /** + * + * @param builderSize + * the size of StringBuilders created within this pool. + */ + public StringBuilderPool(int builderSize) + { + this(DEFAULT_POOL_SIZE, NEVER_CONTRACT, builderSize); + } + + public StringBuilderPool(int poolSize, int builderSize) + { + this(poolSize, NEVER_CONTRACT, builderSize); + } + + /** + * @param poolSize + */ + public StringBuilderPool(int poolSize, int minimumCapacity, int builderSize) + { + this(poolSize, minimumCapacity, builderSize, false); + } + + public StringBuilderPool(int poolSize, int minimumCapacity, int builderSize, + boolean checkMultiRelease) + { + super(poolSize, minimumCapacity, builderSize, checkMultiRelease); + } + + /** + * Alias for acquire(). + * + * @return + */ + public StringBuilder nextBuffer() + { + return this.acquire(); + } + + /** + * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) + */ + @Override + protected void clean(StringBuilder objectToClean) + { + objectToClean.setLength(0); + } + + /** + * @see ecologylab.generic.ResourcePool#generateNewResource() + */ + @Override + protected StringBuilder generateNewResource() + { + return new StringBuilder(this.resourceObjectCapacity); + } + + public String releaseAndGetString(StringBuilder objectToRelease) + { + String s = StringTools.toString(objectToRelease); + this.release(objectToRelease); + return s; + } + + public static void main(String[] args) + { + + StringBuilderPool sbp = new StringBuilderPool(8, 2, 12, true); + System.out.println("0 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + + StringBuilder sb1 = new StringBuilder("asdf"); + StringBuilder sb2 = sb1; + StringBuilder sb3 = sb1; + + sbp.release(sb1); + System.out.println("1 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + sbp.release(sb2); + System.out.println("2 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + sbp.release(sb3); + System.out.println("3 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + + StringBuilder sb4 = sbp.acquire(); + System.out.println("4 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + StringBuilder sb5 = sb4; + + sbp.release(sb5); + System.out.println("5 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + sbp.release(sb4); + System.out.println("6 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + + StringBuilder sb6 = sbp.acquire(); + System.out.println("7 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + StringBuilder sb7 = sbp.acquire(); + System.out.println("8 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + StringBuilder sb8 = sbp.acquire(); + System.out.println("9 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + + sbp.release(sb6); + System.out.println("10 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + sbp.release(sb7); + System.out.println("11 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + sbp.release(sb8); + System.out.println("12 "+sbp.getPoolSize() + "/" + sbp.getCapacity()); + } +} diff --git a/simplCore/src/ecologylab/generic/StringInputStream.java b/simplCore/src/ecologylab/generic/StringInputStream.java index 20083341..cc9ec6f4 100644 --- a/simplCore/src/ecologylab/generic/StringInputStream.java +++ b/simplCore/src/ecologylab/generic/StringInputStream.java @@ -1,141 +1,141 @@ -package ecologylab.generic; - -import java.io.IOException; -import java.io.InputStream; - -/** - * A mechanism for reading Strings from - * java.io.InputStreams of various formats. - * Used especially in drag and drop, for getting values. - */ -public class StringInputStream -extends InputStream -{ - public static final int UTF16_LE = 0; - public static final int UTF16_BE = 1; - public static final int UTF16 = UTF16_LE; - public static final int UTF8 = 2; - - /** - * Little-endian is like Intel. - * Big-endian is like Power PC. - */ - int outputFormat = UTF16_LE; - - /** - * The string from which bytes are read. - */ - protected CharSequence buffer; - - /** - * The index of the next character to read from the input stream buffer. - * - * @see java.io.StringBufferInputStream#buffer - */ - protected int pos; - - /** - * The number of valid characters in the input stream buffer. - * - * @see java.io.StringBufferInputStream#buffer - */ - protected int count; - - /** - * Creates a string input stream to read data from the specified string. - * - * @param charSequence the underlying input buffer. - */ - - public StringInputStream(CharSequence charSequence, int format) - { - this(charSequence); - outputFormat = format; - } - public StringInputStream(CharSequence charSequence) - { - this.buffer = charSequence; - count = charSequence.length(); - } - /** - * Reads the next byte of data from this input stream. The value - * byte is returned as an int in the range - * 0 to 255. If no byte is available - * because the end of the stream has been reached, the value - * -1 is returned. - *

- * The read method of - * StringBufferInputStream cannot block. It returns the - * low eight bits of the next character in this input stream's buffer. - * - * @return the next byte of data, or -1 if the end of the - * stream is reached. - */ - @Override - public synchronized int read() - { -// Debug.println("StringInputStream.read("); - return (pos < count) ? (int)buffer.charAt(pos++) : -1; -// return (pos < count) ? ((int)(buffer.charAt(pos++)) & 0xFFFF) : -1; - } - - @Override -public synchronized int read(byte buf[], int off, int len) - { - // Debug.println("StringInputStream.read(" + len); - if (buf == null) - { - throw new NullPointerException(); - } else if ((off < 0) || (off > buf.length) || (len < 0) || - ((off + len) > buf.length) || ((off + len) < 0)) { - throw new IndexOutOfBoundsException(); - } - if (pos >= count) - { - return -1; - } - if (pos + len > count) - { - len = count - pos; - } - if (len <= 0) - { - return 0; - } - CharSequence s = buffer; - int cnt = len; - while (--cnt >= 0) - { - char thisChar = s.charAt(pos++); - // little endian reverses the byte order - byte b1 = (byte) (thisChar & 0xff); - byte b2 = (byte) (thisChar >> 8); - switch (outputFormat) - { - case UTF8: - buf[off++] = b1; - b2 = 0; - break; - case UTF16_LE: - buf[off++] = b1; - buf[off++] = b2; - break; - case UTF16_BE: - buf[off++] = b2; - buf[off++] = b1; - break; - } - // Debug.println(pos + " " + thisChar + " " + b1 + " " + b2); - } - if (outputFormat != UTF8) - len *= 2; - return len; - } - @Override - public int available() throws IOException - { -// Debug.println("StringBufferInputStream.available()"); - return count - pos; - } - -} +package ecologylab.generic; + +import java.io.IOException; +import java.io.InputStream; + +/** + * A mechanism for reading Strings from + * java.io.InputStreams of various formats. + * Used especially in drag and drop, for getting values. + */ +public class StringInputStream +extends InputStream +{ + public static final int UTF16_LE = 0; + public static final int UTF16_BE = 1; + public static final int UTF16 = UTF16_LE; + public static final int UTF8 = 2; + + /** + * Little-endian is like Intel. + * Big-endian is like Power PC. + */ + int outputFormat = UTF16_LE; + + /** + * The string from which bytes are read. + */ + protected CharSequence buffer; + + /** + * The index of the next character to read from the input stream buffer. + * + * @see java.io.StringBufferInputStream#buffer + */ + protected int pos; + + /** + * The number of valid characters in the input stream buffer. + * + * @see java.io.StringBufferInputStream#buffer + */ + protected int count; + + /** + * Creates a string input stream to read data from the specified string. + * + * @param charSequence the underlying input buffer. + */ + + public StringInputStream(CharSequence charSequence, int format) + { + this(charSequence); + outputFormat = format; + } + public StringInputStream(CharSequence charSequence) + { + this.buffer = charSequence; + count = charSequence.length(); + } + /** + * Reads the next byte of data from this input stream. The value + * byte is returned as an int in the range + * 0 to 255. If no byte is available + * because the end of the stream has been reached, the value + * -1 is returned. + *

+ * The read method of + * StringBufferInputStream cannot block. It returns the + * low eight bits of the next character in this input stream's buffer. + * + * @return the next byte of data, or -1 if the end of the + * stream is reached. + */ + @Override + public synchronized int read() + { +// Debug.println("StringInputStream.read("); + return (pos < count) ? (int)buffer.charAt(pos++) : -1; +// return (pos < count) ? ((int)(buffer.charAt(pos++)) & 0xFFFF) : -1; + } + + @Override +public synchronized int read(byte buf[], int off, int len) + { + // Debug.println("StringInputStream.read(" + len); + if (buf == null) + { + throw new NullPointerException(); + } else if ((off < 0) || (off > buf.length) || (len < 0) || + ((off + len) > buf.length) || ((off + len) < 0)) { + throw new IndexOutOfBoundsException(); + } + if (pos >= count) + { + return -1; + } + if (pos + len > count) + { + len = count - pos; + } + if (len <= 0) + { + return 0; + } + CharSequence s = buffer; + int cnt = len; + while (--cnt >= 0) + { + char thisChar = s.charAt(pos++); + // little endian reverses the byte order + byte b1 = (byte) (thisChar & 0xff); + byte b2 = (byte) (thisChar >> 8); + switch (outputFormat) + { + case UTF8: + buf[off++] = b1; + b2 = 0; + break; + case UTF16_LE: + buf[off++] = b1; + buf[off++] = b2; + break; + case UTF16_BE: + buf[off++] = b2; + buf[off++] = b1; + break; + } + // Debug.println(pos + " " + thisChar + " " + b1 + " " + b2); + } + if (outputFormat != UTF8) + len *= 2; + return len; + } + @Override + public int available() throws IOException + { +// Debug.println("StringBufferInputStream.available()"); + return count - pos; + } + +} diff --git a/simplCore/src/ecologylab/generic/StringTools.java b/simplCore/src/ecologylab/generic/StringTools.java index 10b1e5ff..1aa131ee 100644 --- a/simplCore/src/ecologylab/generic/StringTools.java +++ b/simplCore/src/ecologylab/generic/StringTools.java @@ -12,7 +12,9 @@ import java.nio.charset.CoderResult; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -879,7 +881,11 @@ public static HashMap doubleSplit(String input, String regex1, S // TODO Auto-generated catch block e.printStackTrace(); } - ; + catch (IllegalArgumentException e) + { + error(StringTools.class, "Value cannot be URLDecoded: " + input); + e.printStackTrace(); + } } result.put(split2[0], value); } @@ -947,13 +953,18 @@ public static String unDoubleSplit(HashMap parametersMap, String } public static String join(String delim, String... parts) + { + return join(delim, Arrays.asList(parts)); + } + + public static String join(String delim, List parts) { StringBuilder sb = new StringBuilder(); - for (int i = 0; i < parts.length; ++i) + for (int i = 0; i < parts.size(); ++i) { if (i > 0) sb.append(delim); - sb.append(parts[i]); + sb.append(parts.get(i)); } return sb.toString(); } diff --git a/simplCore/src/ecologylab/generic/SwingTools.java b/simplCore/src/ecologylab/generic/SwingTools.java index 1bd23189..39e99d4f 100644 --- a/simplCore/src/ecologylab/generic/SwingTools.java +++ b/simplCore/src/ecologylab/generic/SwingTools.java @@ -1,199 +1,199 @@ -package ecologylab.generic; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.FlowLayout; -import java.awt.HeadlessException; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -import javax.swing.JButton; -import javax.swing.JColorChooser; -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JRootPane; -import javax.swing.UIManager; - -/** - * Static convenience methods for Swing programing. - * - * @author andruid - */ -public class SwingTools -{ - public static Color showColorChooser(JColorChooser pane, - Component component, - String title) - throws HeadlessException - { - ColorTracker ok = new ColorTracker(pane); - JDialog dialog = new ColorChooserDialog(component, title, true, pane, ok, null); - - dialog.addWindowListener(new ColorChooserDialog.Closer()); - dialog.addComponentListener(new ColorChooserDialog.DisposeOnClose()); - - dialog.show(); // blocks until user brings dialog down... - - return ok.getColor(); - } -} - -/* - * Class which builds a color chooser dialog consisting of - * a JColorChooser with "Ok", "Cancel", and "Reset" buttons. - * - * Note: This needs to be fixed to deal with localization! - */ -class ColorChooserDialog extends JDialog { - private Color initialColor; - private JColorChooser chooserPane; - - public ColorChooserDialog(Component c, String title, boolean modal, - JColorChooser chooserPane, - ActionListener okListener, ActionListener cancelListener) - throws HeadlessException { - super(JOptionPane.getFrameForComponent(c), title, modal); - //setResizable(false); - - this.chooserPane = chooserPane; - - String okString = UIManager.getString("ColorChooser.okText"); - String cancelString = UIManager.getString("ColorChooser.cancelText"); - String resetString = UIManager.getString("ColorChooser.resetText"); - - Container contentPane = getContentPane(); - contentPane.setLayout(new BorderLayout()); - contentPane.add(chooserPane, BorderLayout.CENTER); - - /* - * Create Lower button panel - */ - JPanel buttonPane = new JPanel(); - buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER)); - JButton okButton = new JButton(okString); - getRootPane().setDefaultButton(okButton); - okButton.setActionCommand("OK"); - if (okListener != null) { - okButton.addActionListener(okListener); - } - okButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - hide(); - } - }); - buttonPane.add(okButton); - - JButton cancelButton = new JButton(cancelString); - - // The following few lines are used to register esc to close the dialog -/* Action cancelKeyAction = new AbstractAction() { - public void actionPerformed(ActionEvent e) { - ((AbstractButton)e.getSource()).fireActionPerformed(e); - } - }; - KeyStroke cancelKeyStroke = KeyStroke.getKeyStroke((char)KeyEvent.VK_ESCAPE, false); - InputMap inputMap = cancelButton.getInputMap(JComponent. - WHEN_IN_FOCUSED_WINDOW); - ActionMap actionMap = cancelButton.getActionMap(); - if (inputMap != null && actionMap != null) { - inputMap.put(cancelKeyStroke, "cancel"); - actionMap.put("cancel", cancelKeyAction); - } -*/ // end esc handling - - cancelButton.setActionCommand("cancel"); - if (cancelListener != null) { - cancelButton.addActionListener(cancelListener); - } - cancelButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - hide(); - } - }); - buttonPane.add(cancelButton); - - JButton resetButton = new JButton(resetString); - resetButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - reset(); - } - }); - - /*int mnemonic = UIManager.getInt("ColorChooser.resetMnemonic", -1); - if (mnemonic != -1) { - resetButton.setMnemonic(mnemonic); - } */ - buttonPane.add(resetButton); - contentPane.add(buttonPane, BorderLayout.SOUTH); - - if (JDialog.isDefaultLookAndFeelDecorated()) { - boolean supportsWindowDecorations = - UIManager.getLookAndFeel().getSupportsWindowDecorations(); - if (supportsWindowDecorations) { - getRootPane().setWindowDecorationStyle(JRootPane.COLOR_CHOOSER_DIALOG); - } - } - applyComponentOrientation(((c == null) ? getRootPane() : c).getComponentOrientation()); - - pack(); - setLocationRelativeTo(c); - } - - @Override - public void show() { - initialColor = chooserPane.getColor(); - super.show(); - } - - public void reset() { - chooserPane.setColor(initialColor); - } - - static class Closer extends WindowAdapter - { - @Override - public void windowClosing(WindowEvent e) { - Window w = e.getWindow(); - w.hide(); - } - } - - static class DisposeOnClose extends ComponentAdapter - { - @Override - public void componentHidden(ComponentEvent e) { - Window w = (Window)e.getComponent(); - w.dispose(); - } - } - -} - -class ColorTracker implements ActionListener { - JColorChooser chooser; - Color color; - - public ColorTracker(JColorChooser c) { - chooser = c; - } - - @Override - public void actionPerformed(ActionEvent e) { - color = chooser.getColor(); - } - - public Color getColor() { - return color; - } -} +package ecologylab.generic; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.HeadlessException; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JButton; +import javax.swing.JColorChooser; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRootPane; +import javax.swing.UIManager; + +/** + * Static convenience methods for Swing programing. + * + * @author andruid + */ +public class SwingTools +{ + public static Color showColorChooser(JColorChooser pane, + Component component, + String title) + throws HeadlessException + { + ColorTracker ok = new ColorTracker(pane); + JDialog dialog = new ColorChooserDialog(component, title, true, pane, ok, null); + + dialog.addWindowListener(new ColorChooserDialog.Closer()); + dialog.addComponentListener(new ColorChooserDialog.DisposeOnClose()); + + dialog.show(); // blocks until user brings dialog down... + + return ok.getColor(); + } +} + +/* + * Class which builds a color chooser dialog consisting of + * a JColorChooser with "Ok", "Cancel", and "Reset" buttons. + * + * Note: This needs to be fixed to deal with localization! + */ +class ColorChooserDialog extends JDialog { + private Color initialColor; + private JColorChooser chooserPane; + + public ColorChooserDialog(Component c, String title, boolean modal, + JColorChooser chooserPane, + ActionListener okListener, ActionListener cancelListener) + throws HeadlessException { + super(JOptionPane.getFrameForComponent(c), title, modal); + //setResizable(false); + + this.chooserPane = chooserPane; + + String okString = UIManager.getString("ColorChooser.okText"); + String cancelString = UIManager.getString("ColorChooser.cancelText"); + String resetString = UIManager.getString("ColorChooser.resetText"); + + Container contentPane = getContentPane(); + contentPane.setLayout(new BorderLayout()); + contentPane.add(chooserPane, BorderLayout.CENTER); + + /* + * Create Lower button panel + */ + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER)); + JButton okButton = new JButton(okString); + getRootPane().setDefaultButton(okButton); + okButton.setActionCommand("OK"); + if (okListener != null) { + okButton.addActionListener(okListener); + } + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + hide(); + } + }); + buttonPane.add(okButton); + + JButton cancelButton = new JButton(cancelString); + + // The following few lines are used to register esc to close the dialog +/* Action cancelKeyAction = new AbstractAction() { + public void actionPerformed(ActionEvent e) { + ((AbstractButton)e.getSource()).fireActionPerformed(e); + } + }; + KeyStroke cancelKeyStroke = KeyStroke.getKeyStroke((char)KeyEvent.VK_ESCAPE, false); + InputMap inputMap = cancelButton.getInputMap(JComponent. + WHEN_IN_FOCUSED_WINDOW); + ActionMap actionMap = cancelButton.getActionMap(); + if (inputMap != null && actionMap != null) { + inputMap.put(cancelKeyStroke, "cancel"); + actionMap.put("cancel", cancelKeyAction); + } +*/ // end esc handling + + cancelButton.setActionCommand("cancel"); + if (cancelListener != null) { + cancelButton.addActionListener(cancelListener); + } + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + hide(); + } + }); + buttonPane.add(cancelButton); + + JButton resetButton = new JButton(resetString); + resetButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + reset(); + } + }); + + /*int mnemonic = UIManager.getInt("ColorChooser.resetMnemonic", -1); + if (mnemonic != -1) { + resetButton.setMnemonic(mnemonic); + } */ + buttonPane.add(resetButton); + contentPane.add(buttonPane, BorderLayout.SOUTH); + + if (JDialog.isDefaultLookAndFeelDecorated()) { + boolean supportsWindowDecorations = + UIManager.getLookAndFeel().getSupportsWindowDecorations(); + if (supportsWindowDecorations) { + getRootPane().setWindowDecorationStyle(JRootPane.COLOR_CHOOSER_DIALOG); + } + } + applyComponentOrientation(((c == null) ? getRootPane() : c).getComponentOrientation()); + + pack(); + setLocationRelativeTo(c); + } + + @Override + public void show() { + initialColor = chooserPane.getColor(); + super.show(); + } + + public void reset() { + chooserPane.setColor(initialColor); + } + + static class Closer extends WindowAdapter + { + @Override + public void windowClosing(WindowEvent e) { + Window w = e.getWindow(); + w.hide(); + } + } + + static class DisposeOnClose extends ComponentAdapter + { + @Override + public void componentHidden(ComponentEvent e) { + Window w = (Window)e.getComponent(); + w.dispose(); + } + } + +} + +class ColorTracker implements ActionListener { + JColorChooser chooser; + Color color; + + public ColorTracker(JColorChooser c) { + chooser = c; + } + + @Override + public void actionPerformed(ActionEvent e) { + color = chooser.getColor(); + } + + public Color getColor() { + return color; + } +} diff --git a/simplCore/src/ecologylab/generic/ThreadMaster.java b/simplCore/src/ecologylab/generic/ThreadMaster.java index 51b346ac..2f9dee6d 100644 --- a/simplCore/src/ecologylab/generic/ThreadMaster.java +++ b/simplCore/src/ecologylab/generic/ThreadMaster.java @@ -1,23 +1,23 @@ -package ecologylab.generic; - -/** - * Implement this class in an object that knows about many other threads. - * Then, use the provided methods to have that object pause many - * threads at once. This is done in order to let the CPU concentrate - * on a specific intensive activity, like handling interactive drag and drop, - * or pruning large collections. - */ -public interface -ThreadMaster -{ -/** - * Pause all the threads we know about. - * - * @return true if threads needed to be paused - */ - public boolean pauseThreads(); -/** - * Unpause (continue) all the threads we know about. - */ - public void unpauseThreads(); -} +package ecologylab.generic; + +/** + * Implement this class in an object that knows about many other threads. + * Then, use the provided methods to have that object pause many + * threads at once. This is done in order to let the CPU concentrate + * on a specific intensive activity, like handling interactive drag and drop, + * or pruning large collections. + */ +public interface +ThreadMaster +{ +/** + * Pause all the threads we know about. + * + * @return true if threads needed to be paused + */ + public boolean pauseThreads(); +/** + * Unpause (continue) all the threads we know about. + */ + public void unpauseThreads(); +} diff --git a/simplCore/src/ecologylab/generic/ValueFactory.java b/simplCore/src/ecologylab/generic/ValueFactory.java index 84b6cab0..14b3fc51 100644 --- a/simplCore/src/ecologylab/generic/ValueFactory.java +++ b/simplCore/src/ecologylab/generic/ValueFactory.java @@ -1,13 +1,13 @@ -package ecologylab.generic; - -/** - * Create Value objects for hashed data structure with synchronized writes and unsynchronized reads. - * @author andruid - * - * @param - * @param - */ -public interface ValueFactory -{ - public V constructValue(K key); -} +package ecologylab.generic; + +/** + * Create Value objects for hashed data structure with synchronized writes and unsynchronized reads. + * @author andruid + * + * @param + * @param + */ +public interface ValueFactory +{ + public V constructValue(K key); +} diff --git a/simplCore/src/ecologylab/generic/ValueFactory2.java b/simplCore/src/ecologylab/generic/ValueFactory2.java index bf7e688b..6253ed97 100644 --- a/simplCore/src/ecologylab/generic/ValueFactory2.java +++ b/simplCore/src/ecologylab/generic/ValueFactory2.java @@ -1,14 +1,14 @@ -package ecologylab.generic; - -/** - * Create Value objects for hashed data structure with synchronized writes and unsynchronized reads. - * @author andruid - * - * @param - * @param - * @param 2nd argument to constructor - */ -public interface ValueFactory2 -{ - public V createValue(K key, A arg); -} +package ecologylab.generic; + +/** + * Create Value objects for hashed data structure with synchronized writes and unsynchronized reads. + * @author andruid + * + * @param + * @param + * @param 2nd argument to constructor + */ +public interface ValueFactory2 +{ + public V createValue(K key, A arg); +} diff --git a/simplCore/src/ecologylab/generic/package.html b/simplCore/src/ecologylab/generic/package.html index 2c7be2ec..c75abaf1 100644 --- a/simplCore/src/ecologylab/generic/package.html +++ b/simplCore/src/ecologylab/generic/package.html @@ -1,4 +1,4 @@ - -Basic library building blocks of underlying functionality, in modules -not large enough to warrant individual packages. - + +Basic library building blocks of underlying functionality, in modules +not large enough to warrant individual packages. + diff --git a/simplCore/src/ecologylab/generic/text/DecimalFormatSymbols.java b/simplCore/src/ecologylab/generic/text/DecimalFormatSymbols.java index 3f68bd83..e6660ace 100644 --- a/simplCore/src/ecologylab/generic/text/DecimalFormatSymbols.java +++ b/simplCore/src/ecologylab/generic/text/DecimalFormatSymbols.java @@ -1,603 +1,603 @@ -/* - * @(#)DecimalFormatSymbols.java 1.41 04/05/10 - * - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -/* - * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved - * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved - * - * The original version of this source code and documentation is copyrighted - * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These - * materials are provided under terms of a License Agreement between Taligent - * and Sun. This technology is protected by multiple US and International - * patents. This notice and attribution to Taligent may not be removed. - * Taligent is a registered trademark of Taligent, Inc. - * - */ - -package ecologylab.generic.text; - -import java.io.Serializable; -import java.text.DecimalFormat; -import java.util.Currency; -import java.util.Hashtable; - -/** - * This class represents the set of symbols (such as the decimal separator, the - * grouping separator, and so on) needed by DecimalFormat to - * format numbers. DecimalFormat creates for itself an instance - * of DecimalFormatSymbols from its locale data. If you need to - * change any of these symbols, you can get the - * DecimalFormatSymbols object from your - * DecimalFormat and modify it. - * - * @see java.util.Locale - * @see DecimalFormat - * @version 1.41, 05/10/04 - * @author Mark Davis - * @author Alan Liu - */ - -final public class DecimalFormatSymbols implements Cloneable, Serializable -{ - - /** - * Create a DecimalFormatSymbols object. - */ - public DecimalFormatSymbols() - { - initialize(); - } - - /** - * Gets the character used for zero. Different for Arabic, etc. - */ - public char getZeroDigit() - { - return zeroDigit; - } - - /** - * Sets the character used for zero. Different for Arabic, etc. - */ - public void setZeroDigit(char zeroDigit) - { - this.zeroDigit = zeroDigit; - } - - /** - * Gets the character used for thousands separator. Different for French, - * etc. - */ - public char getGroupingSeparator() - { - return groupingSeparator; - } - - /** - * Sets the character used for thousands separator. Different for French, - * etc. - */ - public void setGroupingSeparator(char groupingSeparator) - { - this.groupingSeparator = groupingSeparator; - } - - /** - * Gets the character used for decimal sign. Different for French, etc. - */ - public char getDecimalSeparator() - { - return decimalSeparator; - } - - /** - * Sets the character used for decimal sign. Different for French, etc. - */ - public void setDecimalSeparator(char decimalSeparator) - { - this.decimalSeparator = decimalSeparator; - } - - /** - * Gets the character used for per mille sign. Different for Arabic, etc. - */ - public char getPerMill() - { - return perMill; - } - - /** - * Sets the character used for per mille sign. Different for Arabic, etc. - */ - public void setPerMill(char perMill) - { - this.perMill = perMill; - } - - /** - * Gets the character used for percent sign. Different for Arabic, etc. - */ - public char getPercent() - { - return percent; - } - - /** - * Sets the character used for percent sign. Different for Arabic, etc. - */ - public void setPercent(char percent) - { - this.percent = percent; - } - - /** - * Gets the character used for a digit in a pattern. - */ - public char getDigit() - { - return digit; - } - - /** - * Sets the character used for a digit in a pattern. - */ - public void setDigit(char digit) - { - this.digit = digit; - } - - /** - * Gets the character used to separate positive and negative subpatterns in a - * pattern. - */ - public char getPatternSeparator() - { - return patternSeparator; - } - - /** - * Sets the character used to separate positive and negative subpatterns in a - * pattern. - */ - public void setPatternSeparator(char patternSeparator) - { - this.patternSeparator = patternSeparator; - } - - /** - * Gets the string used to represent infinity. Almost always left unchanged. - */ - public String getInfinity() - { - return infinity; - } - - /** - * Sets the string used to represent infinity. Almost always left unchanged. - */ - public void setInfinity(String infinity) - { - this.infinity = infinity; - } - - /** - * Gets the string used to represent "not a number". Almost always left - * unchanged. - */ - public String getNaN() - { - return NaN; - } - - /** - * Sets the string used to represent "not a number". Almost always left - * unchanged. - */ - public void setNaN(String NaN) - { - this.NaN = NaN; - } - - /** - * Gets the character used to represent minus sign. If no explicit negative - * format is specified, one is formed by prefixing minusSign to the positive - * format. - */ - public char getMinusSign() - { - return minusSign; - } - - /** - * Sets the character used to represent minus sign. If no explicit negative - * format is specified, one is formed by prefixing minusSign to the positive - * format. - */ - public void setMinusSign(char minusSign) - { - this.minusSign = minusSign; - } - - /** - * Returns the currency symbol for the currency of these DecimalFormatSymbols - * in their locale. - * - * @since 1.2 - */ - public String getCurrencySymbol() - { - return currencySymbol; - } - - /** - * Sets the currency symbol for the currency of these DecimalFormatSymbols in - * their locale. - * - * @since 1.2 - */ - public void setCurrencySymbol(String currency) - { - currencySymbol = currency; - } - - /** - * Returns the ISO 4217 currency code of the currency of these - * DecimalFormatSymbols. - * - * @since 1.2 - */ - public String getInternationalCurrencySymbol() - { - return intlCurrencySymbol; - } - - /** - * Sets the ISO 4217 currency code of the currency of these - * DecimalFormatSymbols. If the currency code is valid (as defined by - * {@link java.util.Currency#getInstance(java.lang.String) Currency.getInstance}), - * this also sets the currency attribute to the corresponding Currency - * instance and the currency symbol attribute to the currency's symbol in the - * DecimalFormatSymbols' locale. If the currency code is not valid, then the - * currency attribute is set to null and the currency symbol attribute is not - * modified. - * - * @see #setCurrency - * @see #setCurrencySymbol - * @since 1.2 - */ - public void setInternationalCurrencySymbol(String currencyCode) - { - intlCurrencySymbol = currencyCode; - currency = null; - if (currencyCode != null) - { - try - { - currency = Currency.getInstance(currencyCode); - currencySymbol = currency.getSymbol(); - } - catch (IllegalArgumentException e) - { - } - } - } - - /** - * Gets the currency of these DecimalFormatSymbols. May be null if the - * currency symbol attribute was previously set to a value that's not a valid - * ISO 4217 currency code. - * - * @return the currency used, or null - * @since 1.4 - */ - public Currency getCurrency() - { - return currency; - } - - /** - * Returns the monetary decimal separator. - * - * @since 1.2 - */ - public char getMonetaryDecimalSeparator() - { - return monetarySeparator; - } - - /** - * Sets the monetary decimal separator. - * - * @since 1.2 - */ - public void setMonetaryDecimalSeparator(char sep) - { - monetarySeparator = sep; - } - - // ------------------------------------------------------------ - // BEGIN Package Private methods ... to be made public later - // ------------------------------------------------------------ - - /** - * Returns the character used to separate the mantissa from the exponent. - */ - char getExponentialSymbol() - { - return exponential; - } - - /** - * Sets the character used to separate the mantissa from the exponent. - */ - void setExponentialSymbol(char exp) - { - exponential = exp; - } - - // ------------------------------------------------------------ - // END Package Private methods ... to be made public later - // ------------------------------------------------------------ - - /** - * Standard override. - */ - @Override - public Object clone() - { - try - { - return super.clone(); - // other fields are bit-copied - } - catch (CloneNotSupportedException e) - { - throw new InternalError(); - } - } - - /** - * Override equals. - */ - @Override - public boolean equals(Object obj) - { - if (obj == null) - return false; - if (this == obj) - return true; - if (getClass() != obj.getClass()) - return false; - DecimalFormatSymbols other = (DecimalFormatSymbols) obj; - return (zeroDigit == other.zeroDigit - && groupingSeparator == other.groupingSeparator - && decimalSeparator == other.decimalSeparator - && percent == other.percent && perMill == other.perMill - && digit == other.digit && minusSign == other.minusSign - && patternSeparator == other.patternSeparator - && infinity.equals(other.infinity) && NaN.equals(other.NaN) - && currencySymbol.equals(other.currencySymbol) - && intlCurrencySymbol.equals(other.intlCurrencySymbol) - && currency == other.currency - && monetarySeparator == other.monetarySeparator); - } - - /** - * Override hashCode. - */ - @Override public int hashCode() - { - int result = zeroDigit; - result = result * 37 + groupingSeparator; - result = result * 37 + decimalSeparator; - return result; - } - - /** - * Initializes the symbols from the LocaleElements resource bundle. - */ - private void initialize() - { - decimalSeparator = '.'; - groupingSeparator = ','; - patternSeparator = ';'; - percent = '%'; - zeroDigit = '0'; - digit = '#'; - minusSign = '-'; - exponential = 'E'; - perMill = '\u00E4'; - infinity = "\u00B0"; - NaN = "NaN"; - currencySymbol = "$"; - intlCurrencySymbol = "USD"; - } - - /** - * Character used for zero. - * - * @serial - * @see #getZeroDigit - */ - private char zeroDigit; - - /** - * Character used for thousands separator. - * - * @serial - * @see #getGroupingSeparator - */ - private char groupingSeparator; - - /** - * Character used for decimal sign. - * - * @serial - * @see #getDecimalSeparator - */ - private char decimalSeparator; - - /** - * Character used for per mille sign. - * - * @serial - * @see #getPerMill - */ - private char perMill; - - /** - * Character used for percent sign. - * - * @serial - * @see #getPercent - */ - private char percent; - - /** - * Character used for a digit in a pattern. - * - * @serial - * @see #getDigit - */ - private char digit; - - /** - * Character used to separate positive and negative subpatterns in a pattern. - * - * @serial - * @see #getPatternSeparator - */ - private char patternSeparator; - - /** - * String used to represent infinity. - * - * @serial - * @see #getInfinity - */ - private String infinity; - - /** - * String used to represent "not a number". - * - * @serial - * @see #getNaN - */ - private String NaN; - - /** - * Character used to represent minus sign. - * - * @serial - * @see #getMinusSign - */ - private char minusSign; - - /** - * String denoting the local currency, e.g. "$". - * - * @serial - * @see #getCurrencySymbol - */ - private String currencySymbol; - - /** - * ISO 4217 currency code denoting the local currency, e.g. "USD". - * - * @serial - * @see #getInternationalCurrencySymbol - */ - private String intlCurrencySymbol; - - /** - * The decimal separator used when formatting currency values. - * - * @serial - * @since JDK 1.1.6 - * @see #getMonetaryDecimalSeparator - */ - private char monetarySeparator; // Field - // new - // in - // JDK - // 1.1.6 - - /** - * The character used to distinguish the exponent in a number formatted in - * exponential notation, e.g. 'E' for a number such as "1.23E45". - *

- * Note that the public API provides no way to set this field, even though it - * is supported by the implementation and the stream format. The intent is - * that this will be added to the API in the future. - * - * @serial - * @since JDK 1.1.6 - */ - private char exponential; // Field - // new - // in - // JDK - // 1.1.6 - - // currency; only the ISO code is serialized. - private transient Currency currency; - - // Proclaim JDK 1.1 FCS compatibility - static final long serialVersionUID = 5772796243397350300L; - - // The internal serial version which says which version was written - // - 0 (default) for version up to JDK 1.1.5 - // - 1 for version from JDK 1.1.6, which includes two new fields: - // monetarySeparator and exponential. - // - 2 for version from J2SE 1.4, which includes locale field. - private static final int currentSerialVersion = 2; - - /** - * Describes the version of DecimalFormatSymbols present on - * the stream. Possible values are: - *

- * When streaming out a DecimalFormatSymbols, the most recent - * format (corresponding to the highest allowable - * serialVersionOnStream) is always written. - * - * @serial - * @since JDK 1.1.6 - */ - private int serialVersionOnStream = currentSerialVersion; - - /** - * cache to hold the NumberElements and the Currency of a Locale. - */ - private static final Hashtable cachedLocaleData = new Hashtable(3); - - public static void main (String[] args) - { - DecimalFormatSymbols s = new DecimalFormatSymbols(); - - System.out.println(s.currencySymbol); - System.out.println(s.decimalSeparator); - System.out.println(s.digit); - System.out.println(s.exponential); - System.out.println(s.groupingSeparator); - System.out.println(s.infinity); - System.out.println(s.intlCurrencySymbol); - System.out.println(s.minusSign); - System.out.println(s.monetarySeparator); - System.out.println(s.NaN); - System.out.println(s.patternSeparator); - System.out.println(s.percent); - System.out.println(s.perMill); - System.out.println(s.zeroDigit); - } -} +/* + * @(#)DecimalFormatSymbols.java 1.41 04/05/10 + * + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +/* + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved + * + * The original version of this source code and documentation is copyrighted + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These + * materials are provided under terms of a License Agreement between Taligent + * and Sun. This technology is protected by multiple US and International + * patents. This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + */ + +package ecologylab.generic.text; + +import java.io.Serializable; +import java.text.DecimalFormat; +import java.util.Currency; +import java.util.Hashtable; + +/** + * This class represents the set of symbols (such as the decimal separator, the + * grouping separator, and so on) needed by DecimalFormat to + * format numbers. DecimalFormat creates for itself an instance + * of DecimalFormatSymbols from its locale data. If you need to + * change any of these symbols, you can get the + * DecimalFormatSymbols object from your + * DecimalFormat and modify it. + * + * @see java.util.Locale + * @see DecimalFormat + * @version 1.41, 05/10/04 + * @author Mark Davis + * @author Alan Liu + */ + +final public class DecimalFormatSymbols implements Cloneable, Serializable +{ + + /** + * Create a DecimalFormatSymbols object. + */ + public DecimalFormatSymbols() + { + initialize(); + } + + /** + * Gets the character used for zero. Different for Arabic, etc. + */ + public char getZeroDigit() + { + return zeroDigit; + } + + /** + * Sets the character used for zero. Different for Arabic, etc. + */ + public void setZeroDigit(char zeroDigit) + { + this.zeroDigit = zeroDigit; + } + + /** + * Gets the character used for thousands separator. Different for French, + * etc. + */ + public char getGroupingSeparator() + { + return groupingSeparator; + } + + /** + * Sets the character used for thousands separator. Different for French, + * etc. + */ + public void setGroupingSeparator(char groupingSeparator) + { + this.groupingSeparator = groupingSeparator; + } + + /** + * Gets the character used for decimal sign. Different for French, etc. + */ + public char getDecimalSeparator() + { + return decimalSeparator; + } + + /** + * Sets the character used for decimal sign. Different for French, etc. + */ + public void setDecimalSeparator(char decimalSeparator) + { + this.decimalSeparator = decimalSeparator; + } + + /** + * Gets the character used for per mille sign. Different for Arabic, etc. + */ + public char getPerMill() + { + return perMill; + } + + /** + * Sets the character used for per mille sign. Different for Arabic, etc. + */ + public void setPerMill(char perMill) + { + this.perMill = perMill; + } + + /** + * Gets the character used for percent sign. Different for Arabic, etc. + */ + public char getPercent() + { + return percent; + } + + /** + * Sets the character used for percent sign. Different for Arabic, etc. + */ + public void setPercent(char percent) + { + this.percent = percent; + } + + /** + * Gets the character used for a digit in a pattern. + */ + public char getDigit() + { + return digit; + } + + /** + * Sets the character used for a digit in a pattern. + */ + public void setDigit(char digit) + { + this.digit = digit; + } + + /** + * Gets the character used to separate positive and negative subpatterns in a + * pattern. + */ + public char getPatternSeparator() + { + return patternSeparator; + } + + /** + * Sets the character used to separate positive and negative subpatterns in a + * pattern. + */ + public void setPatternSeparator(char patternSeparator) + { + this.patternSeparator = patternSeparator; + } + + /** + * Gets the string used to represent infinity. Almost always left unchanged. + */ + public String getInfinity() + { + return infinity; + } + + /** + * Sets the string used to represent infinity. Almost always left unchanged. + */ + public void setInfinity(String infinity) + { + this.infinity = infinity; + } + + /** + * Gets the string used to represent "not a number". Almost always left + * unchanged. + */ + public String getNaN() + { + return NaN; + } + + /** + * Sets the string used to represent "not a number". Almost always left + * unchanged. + */ + public void setNaN(String NaN) + { + this.NaN = NaN; + } + + /** + * Gets the character used to represent minus sign. If no explicit negative + * format is specified, one is formed by prefixing minusSign to the positive + * format. + */ + public char getMinusSign() + { + return minusSign; + } + + /** + * Sets the character used to represent minus sign. If no explicit negative + * format is specified, one is formed by prefixing minusSign to the positive + * format. + */ + public void setMinusSign(char minusSign) + { + this.minusSign = minusSign; + } + + /** + * Returns the currency symbol for the currency of these DecimalFormatSymbols + * in their locale. + * + * @since 1.2 + */ + public String getCurrencySymbol() + { + return currencySymbol; + } + + /** + * Sets the currency symbol for the currency of these DecimalFormatSymbols in + * their locale. + * + * @since 1.2 + */ + public void setCurrencySymbol(String currency) + { + currencySymbol = currency; + } + + /** + * Returns the ISO 4217 currency code of the currency of these + * DecimalFormatSymbols. + * + * @since 1.2 + */ + public String getInternationalCurrencySymbol() + { + return intlCurrencySymbol; + } + + /** + * Sets the ISO 4217 currency code of the currency of these + * DecimalFormatSymbols. If the currency code is valid (as defined by + * {@link java.util.Currency#getInstance(java.lang.String) Currency.getInstance}), + * this also sets the currency attribute to the corresponding Currency + * instance and the currency symbol attribute to the currency's symbol in the + * DecimalFormatSymbols' locale. If the currency code is not valid, then the + * currency attribute is set to null and the currency symbol attribute is not + * modified. + * + * @see #setCurrency + * @see #setCurrencySymbol + * @since 1.2 + */ + public void setInternationalCurrencySymbol(String currencyCode) + { + intlCurrencySymbol = currencyCode; + currency = null; + if (currencyCode != null) + { + try + { + currency = Currency.getInstance(currencyCode); + currencySymbol = currency.getSymbol(); + } + catch (IllegalArgumentException e) + { + } + } + } + + /** + * Gets the currency of these DecimalFormatSymbols. May be null if the + * currency symbol attribute was previously set to a value that's not a valid + * ISO 4217 currency code. + * + * @return the currency used, or null + * @since 1.4 + */ + public Currency getCurrency() + { + return currency; + } + + /** + * Returns the monetary decimal separator. + * + * @since 1.2 + */ + public char getMonetaryDecimalSeparator() + { + return monetarySeparator; + } + + /** + * Sets the monetary decimal separator. + * + * @since 1.2 + */ + public void setMonetaryDecimalSeparator(char sep) + { + monetarySeparator = sep; + } + + // ------------------------------------------------------------ + // BEGIN Package Private methods ... to be made public later + // ------------------------------------------------------------ + + /** + * Returns the character used to separate the mantissa from the exponent. + */ + char getExponentialSymbol() + { + return exponential; + } + + /** + * Sets the character used to separate the mantissa from the exponent. + */ + void setExponentialSymbol(char exp) + { + exponential = exp; + } + + // ------------------------------------------------------------ + // END Package Private methods ... to be made public later + // ------------------------------------------------------------ + + /** + * Standard override. + */ + @Override + public Object clone() + { + try + { + return super.clone(); + // other fields are bit-copied + } + catch (CloneNotSupportedException e) + { + throw new InternalError(); + } + } + + /** + * Override equals. + */ + @Override + public boolean equals(Object obj) + { + if (obj == null) + return false; + if (this == obj) + return true; + if (getClass() != obj.getClass()) + return false; + DecimalFormatSymbols other = (DecimalFormatSymbols) obj; + return (zeroDigit == other.zeroDigit + && groupingSeparator == other.groupingSeparator + && decimalSeparator == other.decimalSeparator + && percent == other.percent && perMill == other.perMill + && digit == other.digit && minusSign == other.minusSign + && patternSeparator == other.patternSeparator + && infinity.equals(other.infinity) && NaN.equals(other.NaN) + && currencySymbol.equals(other.currencySymbol) + && intlCurrencySymbol.equals(other.intlCurrencySymbol) + && currency == other.currency + && monetarySeparator == other.monetarySeparator); + } + + /** + * Override hashCode. + */ + @Override public int hashCode() + { + int result = zeroDigit; + result = result * 37 + groupingSeparator; + result = result * 37 + decimalSeparator; + return result; + } + + /** + * Initializes the symbols from the LocaleElements resource bundle. + */ + private void initialize() + { + decimalSeparator = '.'; + groupingSeparator = ','; + patternSeparator = ';'; + percent = '%'; + zeroDigit = '0'; + digit = '#'; + minusSign = '-'; + exponential = 'E'; + perMill = '\u00E4'; + infinity = "\u00B0"; + NaN = "NaN"; + currencySymbol = "$"; + intlCurrencySymbol = "USD"; + } + + /** + * Character used for zero. + * + * @serial + * @see #getZeroDigit + */ + private char zeroDigit; + + /** + * Character used for thousands separator. + * + * @serial + * @see #getGroupingSeparator + */ + private char groupingSeparator; + + /** + * Character used for decimal sign. + * + * @serial + * @see #getDecimalSeparator + */ + private char decimalSeparator; + + /** + * Character used for per mille sign. + * + * @serial + * @see #getPerMill + */ + private char perMill; + + /** + * Character used for percent sign. + * + * @serial + * @see #getPercent + */ + private char percent; + + /** + * Character used for a digit in a pattern. + * + * @serial + * @see #getDigit + */ + private char digit; + + /** + * Character used to separate positive and negative subpatterns in a pattern. + * + * @serial + * @see #getPatternSeparator + */ + private char patternSeparator; + + /** + * String used to represent infinity. + * + * @serial + * @see #getInfinity + */ + private String infinity; + + /** + * String used to represent "not a number". + * + * @serial + * @see #getNaN + */ + private String NaN; + + /** + * Character used to represent minus sign. + * + * @serial + * @see #getMinusSign + */ + private char minusSign; + + /** + * String denoting the local currency, e.g. "$". + * + * @serial + * @see #getCurrencySymbol + */ + private String currencySymbol; + + /** + * ISO 4217 currency code denoting the local currency, e.g. "USD". + * + * @serial + * @see #getInternationalCurrencySymbol + */ + private String intlCurrencySymbol; + + /** + * The decimal separator used when formatting currency values. + * + * @serial + * @since JDK 1.1.6 + * @see #getMonetaryDecimalSeparator + */ + private char monetarySeparator; // Field + // new + // in + // JDK + // 1.1.6 + + /** + * The character used to distinguish the exponent in a number formatted in + * exponential notation, e.g. 'E' for a number such as "1.23E45". + *

+ * Note that the public API provides no way to set this field, even though it + * is supported by the implementation and the stream format. The intent is + * that this will be added to the API in the future. + * + * @serial + * @since JDK 1.1.6 + */ + private char exponential; // Field + // new + // in + // JDK + // 1.1.6 + + // currency; only the ISO code is serialized. + private transient Currency currency; + + // Proclaim JDK 1.1 FCS compatibility + static final long serialVersionUID = 5772796243397350300L; + + // The internal serial version which says which version was written + // - 0 (default) for version up to JDK 1.1.5 + // - 1 for version from JDK 1.1.6, which includes two new fields: + // monetarySeparator and exponential. + // - 2 for version from J2SE 1.4, which includes locale field. + private static final int currentSerialVersion = 2; + + /** + * Describes the version of DecimalFormatSymbols present on + * the stream. Possible values are: + *

    + *
  • 0 (or uninitialized): versions prior to JDK 1.1.6. + * + *
  • 1: Versions written by JDK 1.1.6 or later, which include two + * new fields: monetarySeparator and exponential. + *
  • 2: Versions written by J2SE 1.4 or later, which include a new + * locale field. + *
+ * When streaming out a DecimalFormatSymbols, the most recent + * format (corresponding to the highest allowable + * serialVersionOnStream) is always written. + * + * @serial + * @since JDK 1.1.6 + */ + private int serialVersionOnStream = currentSerialVersion; + + /** + * cache to hold the NumberElements and the Currency of a Locale. + */ + private static final Hashtable cachedLocaleData = new Hashtable(3); + + public static void main (String[] args) + { + DecimalFormatSymbols s = new DecimalFormatSymbols(); + + System.out.println(s.currencySymbol); + System.out.println(s.decimalSeparator); + System.out.println(s.digit); + System.out.println(s.exponential); + System.out.println(s.groupingSeparator); + System.out.println(s.infinity); + System.out.println(s.intlCurrencySymbol); + System.out.println(s.minusSign); + System.out.println(s.monetarySeparator); + System.out.println(s.NaN); + System.out.println(s.patternSeparator); + System.out.println(s.percent); + System.out.println(s.perMill); + System.out.println(s.zeroDigit); + } +} diff --git a/simplCore/src/ecologylab/generic/text/DigitList.java b/simplCore/src/ecologylab/generic/text/DigitList.java index b90ce311..04808eda 100644 --- a/simplCore/src/ecologylab/generic/text/DigitList.java +++ b/simplCore/src/ecologylab/generic/text/DigitList.java @@ -1,633 +1,633 @@ -/* - * @(#)DigitList.java 1.30 03/12/19 - * - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -/* - * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved - * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved - * - * The original version of this source code and documentation is copyrighted - * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These - * materials are provided under terms of a License Agreement between Taligent - * and Sun. This technology is protected by multiple US and International - * patents. This notice and attribution to Taligent may not be removed. - * Taligent is a registered trademark of Taligent, Inc. - * - */ - -package ecologylab.generic.text; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.text.ChoiceFormat; -import java.text.DecimalFormat; -import java.text.MessageFormat; -import java.text.NumberFormat; -import java.util.Locale; - -/** - * Digit List. Private to DecimalFormat. - * Handles the transcoding - * between numeric values and strings of characters. Only handles - * non-negative numbers. The division of labor between DigitList and - * DecimalFormat is that DigitList handles the radix 10 representation - * issues; DecimalFormat handles the locale-specific issues such as - * positive/negative, grouping, decimal point, currency, and so on. - * - * A DigitList is really a representation of a floating point value. - * It may be an integer value; we assume that a double has sufficient - * precision to represent all digits of a long. - * - * The DigitList representation consists of a string of characters, - * which are the digits radix 10, from '0' to '9'. It also has a radix - * 10 exponent associated with it. The value represented by a DigitList - * object can be computed by mulitplying the fraction f, where 0 <= f < 1, - * derived by placing all the digits of the list to the right of the - * decimal point, by 10^exponent. - * - * @see Locale - * @see Format - * @see NumberFormat - * @see DecimalFormat - * @see ChoiceFormat - * @see MessageFormat - * @version 1.30 12/19/03 - * @author Mark Davis, Alan Liu - */ -final class DigitList implements Cloneable { - /** - * The maximum number of significant digits in an IEEE 754 double, that - * is, in a Java double. This must not be increased, or garbage digits - * will be generated, and should not be decreased, or accuracy will be lost. - */ - public static final int MAX_COUNT = 19; // == Long.toString(Long.MAX_VALUE).length() - - /** - * These data members are intentionally public and can be set directly. - * - * The value represented is given by placing the decimal point before - * digits[decimalAt]. If decimalAt is < 0, then leading zeros between - * the decimal point and the first nonzero digit are implied. If decimalAt - * is > count, then trailing zeros between the digits[count-1] and the - * decimal point are implied. - * - * Equivalently, the represented value is given by f * 10^decimalAt. Here - * f is a value 0.1 <= f < 1 arrived at by placing the digits in Digits to - * the right of the decimal. - * - * DigitList is normalized, so if it is non-zero, figits[0] is non-zero. We - * don't allow denormalized numbers because our exponent is effectively of - * unlimited magnitude. The count value contains the number of significant - * digits present in digits[]. - * - * Zero is represented by any DigitList with count == 0 or with each digits[i] - * for all i <= count == '0'. - */ - public int decimalAt = 0; - public int count = 0; - public char[] digits = new char[MAX_COUNT]; - - private char[] data; - - /** - * Return true if the represented number is zero. - */ - boolean isZero() { - for (int i=0; i < count; ++i) { - if (digits[i] != '0') { - return false; - } - } - return true; - } - - /** - * Clears out the digits. - * Use before appending them. - * Typically, you set a series of digits with append, then at the point - * you hit the decimal point, you set myDigitList.decimalAt = myDigitList.count; - * then go on appending digits. - */ - public void clear () { - decimalAt = 0; - count = 0; - } - - /** - * Appends a digit to the list, extending the list when necessary. - */ - public void append(char digit) { - if (count == digits.length) { - char[] data = new char[count + 100]; - System.arraycopy(digits, 0, data, 0, count); - digits = data; - } - digits[count++] = digit; - } - - /** - * Utility routine to get the value of the digit list - * If (count == 0) this throws a NumberFormatException, which - * mimics Long.parseLong(). - */ - public final double getDouble() { - if (count == 0) { - return 0.0; - } - - StringBuffer temp = getStringBuffer(); - temp.append('.'); - temp.append(digits, 0, count); - temp.append('E'); - temp.append(decimalAt); - return Double.parseDouble(temp.toString()); - } - - /** - * Utility routine to get the value of the digit list. - * If (count == 0) this returns 0, unlike Long.parseLong(). - */ - public final long getLong() { - // for now, simple implementation; later, do proper IEEE native stuff - - if (count == 0) { - return 0; - } - - // We have to check for this, because this is the one NEGATIVE value - // we represent. If we tried to just pass the digits off to parseLong, - // we'd get a parse failure. - if (isLongMIN_VALUE()) { - return Long.MIN_VALUE; - } - - StringBuffer temp = getStringBuffer(); - temp.append(digits, 0, count); - for (int i = count; i < decimalAt; ++i) { - temp.append('0'); - } - return Long.parseLong(temp.toString()); - } - - public final BigDecimal getBigDecimal() { - if (count == 0) { - if (decimalAt == 0) { - return BigDecimal.ZERO; - } else { - return new BigDecimal("0E" + decimalAt); - } - } - - StringBuffer temp = new StringBuffer(count + 12); - temp.append('.'); - temp.append(digits, 0, count); - temp.append('E'); - temp.append(decimalAt); - return new BigDecimal(temp.toString()); - } - - /** - * Return true if the number represented by this object can fit into - * a long. - * @param isPositive true if this number should be regarded as positive - * @param ignoreNegativeZero true if -0 should be regarded as identical to - * +0; otherwise they are considered distinct - * @return true if this number fits into a Java long - */ - boolean fitsIntoLong(boolean isPositive, boolean ignoreNegativeZero) { - // Figure out if the result will fit in a long. We have to - // first look for nonzero digits after the decimal point; - // then check the size. If the digit count is 18 or less, then - // the value can definitely be represented as a long. If it is 19 - // then it may be too large. - - // Trim trailing zeros. This does not change the represented value. - while (count > 0 && digits[count - 1] == '0') { - --count; - } - - if (count == 0) { - // Positive zero fits into a long, but negative zero can only - // be represented as a double. - bug 4162852 - return isPositive || ignoreNegativeZero; - } - - if (decimalAt < count || decimalAt > MAX_COUNT) { - return false; - } - - if (decimalAt < MAX_COUNT) return true; - - // At this point we have decimalAt == count, and count == MAX_COUNT. - // The number will overflow if it is larger than 9223372036854775807 - // or smaller than -9223372036854775808. - for (int i=0; i max) return false; - if (dig < max) return true; - } - - // At this point the first count digits match. If decimalAt is less - // than count, then the remaining digits are zero, and we return true. - if (count < decimalAt) return true; - - // Now we have a representation of Long.MIN_VALUE, without the leading - // negative sign. If this represents a positive value, then it does - // not fit; otherwise it fits. - return !isPositive; - } - - /** - * Set the digit list to a representation of the given double value. - * This method supports fixed-point notation. - * @param source Value to be converted; must not be Inf, -Inf, Nan, - * or a value <= 0. - * @param maximumFractionDigits The most fractional digits which should - * be converted. - */ - public final void set(double source, int maximumFractionDigits) { - set(source, maximumFractionDigits, true); - } - - /** - * Set the digit list to a representation of the given double value. - * This method supports both fixed-point and exponential notation. - * @param source Value to be converted; must not be Inf, -Inf, Nan, - * or a value <= 0. - * @param maximumDigits The most fractional or total digits which should - * be converted. - * @param fixedPoint If true, then maximumDigits is the maximum - * fractional digits to be converted. If false, total digits. - */ - final void set(double source, int maximumDigits, boolean fixedPoint) { - set(Double.toString(source), maximumDigits, fixedPoint); - } - - /** - * Generate a representation of the form DDDDD, DDDDD.DDDDD, or - * DDDDDE+/-DDDDD. - */ - final void set(String s, int maximumDigits, boolean fixedPoint) { - int len = s.length(); - char[] source = getDataChars(len); - s.getChars(0, len, source, 0); - - decimalAt = -1; - count = 0; - int exponent = 0; - // Number of zeros between decimal point and first non-zero digit after - // decimal point, for numbers < 1. - int leadingZerosAfterDecimal = 0; - boolean nonZeroDigitSeen = false; - - for (int i = 0; i < len; ) { - char c = source[i++]; - if (c == '.') { - decimalAt = count; - } else if (c == 'e' || c == 'E') { - exponent = parseInt(source, i, len); - break; - } else { - if (!nonZeroDigitSeen) { - nonZeroDigitSeen = (c != '0'); - if (!nonZeroDigitSeen && decimalAt != -1) - ++leadingZerosAfterDecimal; - } - if (nonZeroDigitSeen) { - digits[count++] = c; - } - } - } - if (decimalAt == -1) { - decimalAt = count; - } - if (nonZeroDigitSeen) { - decimalAt += exponent - leadingZerosAfterDecimal; - } - - if (fixedPoint) { - // The negative of the exponent represents the number of leading - // zeros between the decimal and the first non-zero digit, for - // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2). If this - // is more than the maximum fraction digits, then we have an underflow - // for the printed representation. - if (-decimalAt > maximumDigits) { - // Handle an underflow to zero when we round something like - // 0.0009 to 2 fractional digits. - count = 0; - return; - } else if (-decimalAt == maximumDigits) { - // If we round 0.0009 to 3 fractional digits, then we have to - // create a new one digit in the least significant location. - if (shouldRoundUp(0)) { - count = 1; - ++decimalAt; - digits[0] = '1'; - } else { - count = 0; - } - return; - } - // else fall through - } - - // Eliminate trailing zeros. - while (count > 1 && digits[count - 1] == '0') { - --count; - } - - // Eliminate digits beyond maximum digits to be displayed. - // Round up if appropriate. - round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits); - } - - /** - * Round the representation to the given number of digits. - * @param maximumDigits The maximum number of digits to be shown. - * Upon return, count will be less than or equal to maximumDigits. - */ - private final void round(int maximumDigits) { - // Eliminate digits beyond maximum digits to be displayed. - // Round up if appropriate. - if (maximumDigits >= 0 && maximumDigits < count) { - if (shouldRoundUp(maximumDigits)) { - // Rounding up involved incrementing digits from LSD to MSD. - // In most cases this is simple, but in a worst case situation - // (9999..99) we have to adjust the decimalAt value. - for (;;) { - --maximumDigits; - if (maximumDigits < 0) { - // We have all 9's, so we increment to a single digit - // of one and adjust the exponent. - digits[0] = '1'; - ++decimalAt; - maximumDigits = 0; // Adjust the count - break; - } - - ++digits[maximumDigits]; - if (digits[maximumDigits] <= '9') break; - // digits[maximumDigits] = '0'; // Unnecessary since we'll truncate this - } - ++maximumDigits; // Increment for use as count - } - count = maximumDigits; - - // Eliminate trailing zeros. - while (count > 1 && digits[count-1] == '0') { - --count; - } - } - } - - - /** - * Return true if truncating the representation to the given number - * of digits will result in an increment to the last digit. This - * method implements half-even rounding, the default rounding mode. - * [bnf] - * @param maximumDigits the number of digits to keep, from 0 to - * count-1. If 0, then all digits are rounded away, and - * this method returns true if a one should be generated (e.g., formatting - * 0.09 with "#.#"). - * @return true if digit maximumDigits-1 should be - * incremented - */ - private boolean shouldRoundUp(int maximumDigits) { - boolean increment = false; - // Implement IEEE half-even rounding - if (maximumDigits < count) { - if (digits[maximumDigits] > '5') { - return true; - } else if (digits[maximumDigits] == '5' ) { - for (int i=maximumDigits+1; i 0 && (digits[maximumDigits-1] % 2 != 0); - } - } - return false; - } - - /** - * Utility routine to set the value of the digit list from a long - */ - public final void set(long source) { - set(source, 0); - } - - /** - * Set the digit list to a representation of the given long value. - * @param source Value to be converted; must be >= 0 or == - * Long.MIN_VALUE. - * @param maximumDigits The most digits which should be converted. - * If maximumDigits is lower than the number of significant digits - * in source, the representation will be rounded. Ignored if <= 0. - */ - public final void set(long source, int maximumDigits) { - // This method does not expect a negative number. However, - // "source" can be a Long.MIN_VALUE (-9223372036854775808), - // if the number being formatted is a Long.MIN_VALUE. In that - // case, it will be formatted as -Long.MIN_VALUE, a number - // which is outside the legal range of a long, but which can - // be represented by DigitList. - if (source <= 0) { - if (source == Long.MIN_VALUE) { - decimalAt = count = MAX_COUNT; - System.arraycopy(LONG_MIN_REP, 0, digits, 0, count); - } else { - decimalAt = count = 0; // Values <= 0 format as zero - } - } else { - // Rewritten to improve performance. I used to call - // Long.toString(), which was about 4x slower than this code. - int left = MAX_COUNT; - int right; - while (source > 0) { - digits[--left] = (char)('0' + (source % 10)); - source /= 10; - } - decimalAt = MAX_COUNT - left; - // Don't copy trailing zeros. We are guaranteed that there is at - // least one non-zero digit, so we don't have to check lower bounds. - for (right = MAX_COUNT - 1; digits[right] == '0'; --right) - ; - count = right - left + 1; - System.arraycopy(digits, left, digits, 0, count); - } - if (maximumDigits > 0) round(maximumDigits); - } - - /** - * Set the digit list to a representation of the given BigDecimal value. - * This method supports both fixed-point and exponential notation. - * @param source Value to be converted; must not be a value <= 0. - * @param maximumDigits The most fractional or total digits which should - * be converted. - * @param fixedPoint If true, then maximumDigits is the maximum - * fractional digits to be converted. If false, total digits. - */ - final void set(BigDecimal source, int maximumDigits, boolean fixedPoint) { - String s = source.toString(); - extendDigits(s.length()); - - set(s, maximumDigits, fixedPoint); - } - - /** - * Set the digit list to a representation of the given BigInteger value. - * @param source Value to be converted; must be >= 0. - * @param maximumDigits The most digits which should be converted. - * If maximumDigits is lower than the number of significant digits - * in source, the representation will be rounded. Ignored if <= 0. - */ - final void set(BigInteger source, int maximumDigits) { - String s = source.toString(); - int len = s.length(); - extendDigits(len); - s.getChars(0, len, digits, 0); - - decimalAt = len; - int right; - for (right = len - 1; right >= 0 && digits[right] == '0'; --right) - ; - count = right + 1; - - if (maximumDigits > 0) { - round(maximumDigits); - } - } - - /** - * equality test between two digit lists. - */ - @Override - public boolean equals(Object obj) { - if (this == obj) // quick check - return true; - if (!(obj instanceof DigitList)) // (1) same object? - return false; - DigitList other = (DigitList) obj; - if (count != other.count || - decimalAt != other.decimalAt) - return false; - for (int i = 0; i < count; i++) - if (digits[i] != other.digits[i]) - return false; - return true; - } - - /** - * Generates the hash code for the digit list. - */ - @Override - public int hashCode() { - int hashcode = decimalAt; - - for (int i = 0; i < count; i++) { - hashcode = hashcode * 37 + digits[i]; - } - - return hashcode; - } - - /** - * Creates a copy of this object. - * @return a clone of this instance. - */ - @Override - public Object clone() { - try { - DigitList other = (DigitList) super.clone(); - char[] newDigits = new char[digits.length]; - System.arraycopy(digits, 0, newDigits, 0, digits.length); - other.digits = newDigits; - return other; - } catch (CloneNotSupportedException e) { - throw new InternalError(); - } - } - - /** - * Returns true if this DigitList represents Long.MIN_VALUE; - * false, otherwise. This is required so that getLong() works. - */ - private boolean isLongMIN_VALUE() { - if (decimalAt != count || count != MAX_COUNT) { - return false; - } - - for (int i = 0; i < count; ++i) { - if (digits[i] != LONG_MIN_REP[i]) return false; - } - - return true; - } - - private static final int parseInt(char[] str, int offset, int strLen) { - char c; - boolean positive = true; - if ((c = str[offset]) == '-') { - positive = false; - offset++; - } else if (c == '+') { - offset++; - } - - int value = 0; - while (offset < strLen) { - c = str[offset++]; - if (c >= '0' && c <= '9') { - value = value * 10 + (c - '0'); - } else { - break; - } - } - return positive ? value : -value; - } - - // The digit part of -9223372036854775808L - private static final char[] LONG_MIN_REP = "9223372036854775808".toCharArray(); - - @Override - public String toString() { - if (isZero()) { - return "0"; - } - StringBuffer buf = getStringBuffer(); - buf.append("0."); - buf.append(digits, 0, count); - buf.append("x10^"); - buf.append(decimalAt); - return buf.toString(); - } - - private StringBuffer tempBuffer; - - private StringBuffer getStringBuffer() { - if (tempBuffer == null) { - tempBuffer = new StringBuffer(MAX_COUNT); - } else { - tempBuffer.setLength(0); - } - return tempBuffer; - } - - private void extendDigits(int len) { - if (len > digits.length) { - digits = new char[len]; - } - } - - private final char[] getDataChars(int length) { - if (data == null || data.length < length) { - data = new char[length]; - } - return data; - } -} +/* + * @(#)DigitList.java 1.30 03/12/19 + * + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +/* + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved + * + * The original version of this source code and documentation is copyrighted + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These + * materials are provided under terms of a License Agreement between Taligent + * and Sun. This technology is protected by multiple US and International + * patents. This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + */ + +package ecologylab.generic.text; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.ChoiceFormat; +import java.text.DecimalFormat; +import java.text.MessageFormat; +import java.text.NumberFormat; +import java.util.Locale; + +/** + * Digit List. Private to DecimalFormat. + * Handles the transcoding + * between numeric values and strings of characters. Only handles + * non-negative numbers. The division of labor between DigitList and + * DecimalFormat is that DigitList handles the radix 10 representation + * issues; DecimalFormat handles the locale-specific issues such as + * positive/negative, grouping, decimal point, currency, and so on. + * + * A DigitList is really a representation of a floating point value. + * It may be an integer value; we assume that a double has sufficient + * precision to represent all digits of a long. + * + * The DigitList representation consists of a string of characters, + * which are the digits radix 10, from '0' to '9'. It also has a radix + * 10 exponent associated with it. The value represented by a DigitList + * object can be computed by mulitplying the fraction f, where 0 <= f < 1, + * derived by placing all the digits of the list to the right of the + * decimal point, by 10^exponent. + * + * @see Locale + * @see Format + * @see NumberFormat + * @see DecimalFormat + * @see ChoiceFormat + * @see MessageFormat + * @version 1.30 12/19/03 + * @author Mark Davis, Alan Liu + */ +final class DigitList implements Cloneable { + /** + * The maximum number of significant digits in an IEEE 754 double, that + * is, in a Java double. This must not be increased, or garbage digits + * will be generated, and should not be decreased, or accuracy will be lost. + */ + public static final int MAX_COUNT = 19; // == Long.toString(Long.MAX_VALUE).length() + + /** + * These data members are intentionally public and can be set directly. + * + * The value represented is given by placing the decimal point before + * digits[decimalAt]. If decimalAt is < 0, then leading zeros between + * the decimal point and the first nonzero digit are implied. If decimalAt + * is > count, then trailing zeros between the digits[count-1] and the + * decimal point are implied. + * + * Equivalently, the represented value is given by f * 10^decimalAt. Here + * f is a value 0.1 <= f < 1 arrived at by placing the digits in Digits to + * the right of the decimal. + * + * DigitList is normalized, so if it is non-zero, figits[0] is non-zero. We + * don't allow denormalized numbers because our exponent is effectively of + * unlimited magnitude. The count value contains the number of significant + * digits present in digits[]. + * + * Zero is represented by any DigitList with count == 0 or with each digits[i] + * for all i <= count == '0'. + */ + public int decimalAt = 0; + public int count = 0; + public char[] digits = new char[MAX_COUNT]; + + private char[] data; + + /** + * Return true if the represented number is zero. + */ + boolean isZero() { + for (int i=0; i < count; ++i) { + if (digits[i] != '0') { + return false; + } + } + return true; + } + + /** + * Clears out the digits. + * Use before appending them. + * Typically, you set a series of digits with append, then at the point + * you hit the decimal point, you set myDigitList.decimalAt = myDigitList.count; + * then go on appending digits. + */ + public void clear () { + decimalAt = 0; + count = 0; + } + + /** + * Appends a digit to the list, extending the list when necessary. + */ + public void append(char digit) { + if (count == digits.length) { + char[] data = new char[count + 100]; + System.arraycopy(digits, 0, data, 0, count); + digits = data; + } + digits[count++] = digit; + } + + /** + * Utility routine to get the value of the digit list + * If (count == 0) this throws a NumberFormatException, which + * mimics Long.parseLong(). + */ + public final double getDouble() { + if (count == 0) { + return 0.0; + } + + StringBuffer temp = getStringBuffer(); + temp.append('.'); + temp.append(digits, 0, count); + temp.append('E'); + temp.append(decimalAt); + return Double.parseDouble(temp.toString()); + } + + /** + * Utility routine to get the value of the digit list. + * If (count == 0) this returns 0, unlike Long.parseLong(). + */ + public final long getLong() { + // for now, simple implementation; later, do proper IEEE native stuff + + if (count == 0) { + return 0; + } + + // We have to check for this, because this is the one NEGATIVE value + // we represent. If we tried to just pass the digits off to parseLong, + // we'd get a parse failure. + if (isLongMIN_VALUE()) { + return Long.MIN_VALUE; + } + + StringBuffer temp = getStringBuffer(); + temp.append(digits, 0, count); + for (int i = count; i < decimalAt; ++i) { + temp.append('0'); + } + return Long.parseLong(temp.toString()); + } + + public final BigDecimal getBigDecimal() { + if (count == 0) { + if (decimalAt == 0) { + return BigDecimal.ZERO; + } else { + return new BigDecimal("0E" + decimalAt); + } + } + + StringBuffer temp = new StringBuffer(count + 12); + temp.append('.'); + temp.append(digits, 0, count); + temp.append('E'); + temp.append(decimalAt); + return new BigDecimal(temp.toString()); + } + + /** + * Return true if the number represented by this object can fit into + * a long. + * @param isPositive true if this number should be regarded as positive + * @param ignoreNegativeZero true if -0 should be regarded as identical to + * +0; otherwise they are considered distinct + * @return true if this number fits into a Java long + */ + boolean fitsIntoLong(boolean isPositive, boolean ignoreNegativeZero) { + // Figure out if the result will fit in a long. We have to + // first look for nonzero digits after the decimal point; + // then check the size. If the digit count is 18 or less, then + // the value can definitely be represented as a long. If it is 19 + // then it may be too large. + + // Trim trailing zeros. This does not change the represented value. + while (count > 0 && digits[count - 1] == '0') { + --count; + } + + if (count == 0) { + // Positive zero fits into a long, but negative zero can only + // be represented as a double. - bug 4162852 + return isPositive || ignoreNegativeZero; + } + + if (decimalAt < count || decimalAt > MAX_COUNT) { + return false; + } + + if (decimalAt < MAX_COUNT) return true; + + // At this point we have decimalAt == count, and count == MAX_COUNT. + // The number will overflow if it is larger than 9223372036854775807 + // or smaller than -9223372036854775808. + for (int i=0; i max) return false; + if (dig < max) return true; + } + + // At this point the first count digits match. If decimalAt is less + // than count, then the remaining digits are zero, and we return true. + if (count < decimalAt) return true; + + // Now we have a representation of Long.MIN_VALUE, without the leading + // negative sign. If this represents a positive value, then it does + // not fit; otherwise it fits. + return !isPositive; + } + + /** + * Set the digit list to a representation of the given double value. + * This method supports fixed-point notation. + * @param source Value to be converted; must not be Inf, -Inf, Nan, + * or a value <= 0. + * @param maximumFractionDigits The most fractional digits which should + * be converted. + */ + public final void set(double source, int maximumFractionDigits) { + set(source, maximumFractionDigits, true); + } + + /** + * Set the digit list to a representation of the given double value. + * This method supports both fixed-point and exponential notation. + * @param source Value to be converted; must not be Inf, -Inf, Nan, + * or a value <= 0. + * @param maximumDigits The most fractional or total digits which should + * be converted. + * @param fixedPoint If true, then maximumDigits is the maximum + * fractional digits to be converted. If false, total digits. + */ + final void set(double source, int maximumDigits, boolean fixedPoint) { + set(Double.toString(source), maximumDigits, fixedPoint); + } + + /** + * Generate a representation of the form DDDDD, DDDDD.DDDDD, or + * DDDDDE+/-DDDDD. + */ + final void set(String s, int maximumDigits, boolean fixedPoint) { + int len = s.length(); + char[] source = getDataChars(len); + s.getChars(0, len, source, 0); + + decimalAt = -1; + count = 0; + int exponent = 0; + // Number of zeros between decimal point and first non-zero digit after + // decimal point, for numbers < 1. + int leadingZerosAfterDecimal = 0; + boolean nonZeroDigitSeen = false; + + for (int i = 0; i < len; ) { + char c = source[i++]; + if (c == '.') { + decimalAt = count; + } else if (c == 'e' || c == 'E') { + exponent = parseInt(source, i, len); + break; + } else { + if (!nonZeroDigitSeen) { + nonZeroDigitSeen = (c != '0'); + if (!nonZeroDigitSeen && decimalAt != -1) + ++leadingZerosAfterDecimal; + } + if (nonZeroDigitSeen) { + digits[count++] = c; + } + } + } + if (decimalAt == -1) { + decimalAt = count; + } + if (nonZeroDigitSeen) { + decimalAt += exponent - leadingZerosAfterDecimal; + } + + if (fixedPoint) { + // The negative of the exponent represents the number of leading + // zeros between the decimal and the first non-zero digit, for + // a value < 0.1 (e.g., for 0.00123, -decimalAt == 2). If this + // is more than the maximum fraction digits, then we have an underflow + // for the printed representation. + if (-decimalAt > maximumDigits) { + // Handle an underflow to zero when we round something like + // 0.0009 to 2 fractional digits. + count = 0; + return; + } else if (-decimalAt == maximumDigits) { + // If we round 0.0009 to 3 fractional digits, then we have to + // create a new one digit in the least significant location. + if (shouldRoundUp(0)) { + count = 1; + ++decimalAt; + digits[0] = '1'; + } else { + count = 0; + } + return; + } + // else fall through + } + + // Eliminate trailing zeros. + while (count > 1 && digits[count - 1] == '0') { + --count; + } + + // Eliminate digits beyond maximum digits to be displayed. + // Round up if appropriate. + round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits); + } + + /** + * Round the representation to the given number of digits. + * @param maximumDigits The maximum number of digits to be shown. + * Upon return, count will be less than or equal to maximumDigits. + */ + private final void round(int maximumDigits) { + // Eliminate digits beyond maximum digits to be displayed. + // Round up if appropriate. + if (maximumDigits >= 0 && maximumDigits < count) { + if (shouldRoundUp(maximumDigits)) { + // Rounding up involved incrementing digits from LSD to MSD. + // In most cases this is simple, but in a worst case situation + // (9999..99) we have to adjust the decimalAt value. + for (;;) { + --maximumDigits; + if (maximumDigits < 0) { + // We have all 9's, so we increment to a single digit + // of one and adjust the exponent. + digits[0] = '1'; + ++decimalAt; + maximumDigits = 0; // Adjust the count + break; + } + + ++digits[maximumDigits]; + if (digits[maximumDigits] <= '9') break; + // digits[maximumDigits] = '0'; // Unnecessary since we'll truncate this + } + ++maximumDigits; // Increment for use as count + } + count = maximumDigits; + + // Eliminate trailing zeros. + while (count > 1 && digits[count-1] == '0') { + --count; + } + } + } + + + /** + * Return true if truncating the representation to the given number + * of digits will result in an increment to the last digit. This + * method implements half-even rounding, the default rounding mode. + * [bnf] + * @param maximumDigits the number of digits to keep, from 0 to + * count-1. If 0, then all digits are rounded away, and + * this method returns true if a one should be generated (e.g., formatting + * 0.09 with "#.#"). + * @return true if digit maximumDigits-1 should be + * incremented + */ + private boolean shouldRoundUp(int maximumDigits) { + boolean increment = false; + // Implement IEEE half-even rounding + if (maximumDigits < count) { + if (digits[maximumDigits] > '5') { + return true; + } else if (digits[maximumDigits] == '5' ) { + for (int i=maximumDigits+1; i 0 && (digits[maximumDigits-1] % 2 != 0); + } + } + return false; + } + + /** + * Utility routine to set the value of the digit list from a long + */ + public final void set(long source) { + set(source, 0); + } + + /** + * Set the digit list to a representation of the given long value. + * @param source Value to be converted; must be >= 0 or == + * Long.MIN_VALUE. + * @param maximumDigits The most digits which should be converted. + * If maximumDigits is lower than the number of significant digits + * in source, the representation will be rounded. Ignored if <= 0. + */ + public final void set(long source, int maximumDigits) { + // This method does not expect a negative number. However, + // "source" can be a Long.MIN_VALUE (-9223372036854775808), + // if the number being formatted is a Long.MIN_VALUE. In that + // case, it will be formatted as -Long.MIN_VALUE, a number + // which is outside the legal range of a long, but which can + // be represented by DigitList. + if (source <= 0) { + if (source == Long.MIN_VALUE) { + decimalAt = count = MAX_COUNT; + System.arraycopy(LONG_MIN_REP, 0, digits, 0, count); + } else { + decimalAt = count = 0; // Values <= 0 format as zero + } + } else { + // Rewritten to improve performance. I used to call + // Long.toString(), which was about 4x slower than this code. + int left = MAX_COUNT; + int right; + while (source > 0) { + digits[--left] = (char)('0' + (source % 10)); + source /= 10; + } + decimalAt = MAX_COUNT - left; + // Don't copy trailing zeros. We are guaranteed that there is at + // least one non-zero digit, so we don't have to check lower bounds. + for (right = MAX_COUNT - 1; digits[right] == '0'; --right) + ; + count = right - left + 1; + System.arraycopy(digits, left, digits, 0, count); + } + if (maximumDigits > 0) round(maximumDigits); + } + + /** + * Set the digit list to a representation of the given BigDecimal value. + * This method supports both fixed-point and exponential notation. + * @param source Value to be converted; must not be a value <= 0. + * @param maximumDigits The most fractional or total digits which should + * be converted. + * @param fixedPoint If true, then maximumDigits is the maximum + * fractional digits to be converted. If false, total digits. + */ + final void set(BigDecimal source, int maximumDigits, boolean fixedPoint) { + String s = source.toString(); + extendDigits(s.length()); + + set(s, maximumDigits, fixedPoint); + } + + /** + * Set the digit list to a representation of the given BigInteger value. + * @param source Value to be converted; must be >= 0. + * @param maximumDigits The most digits which should be converted. + * If maximumDigits is lower than the number of significant digits + * in source, the representation will be rounded. Ignored if <= 0. + */ + final void set(BigInteger source, int maximumDigits) { + String s = source.toString(); + int len = s.length(); + extendDigits(len); + s.getChars(0, len, digits, 0); + + decimalAt = len; + int right; + for (right = len - 1; right >= 0 && digits[right] == '0'; --right) + ; + count = right + 1; + + if (maximumDigits > 0) { + round(maximumDigits); + } + } + + /** + * equality test between two digit lists. + */ + @Override + public boolean equals(Object obj) { + if (this == obj) // quick check + return true; + if (!(obj instanceof DigitList)) // (1) same object? + return false; + DigitList other = (DigitList) obj; + if (count != other.count || + decimalAt != other.decimalAt) + return false; + for (int i = 0; i < count; i++) + if (digits[i] != other.digits[i]) + return false; + return true; + } + + /** + * Generates the hash code for the digit list. + */ + @Override + public int hashCode() { + int hashcode = decimalAt; + + for (int i = 0; i < count; i++) { + hashcode = hashcode * 37 + digits[i]; + } + + return hashcode; + } + + /** + * Creates a copy of this object. + * @return a clone of this instance. + */ + @Override + public Object clone() { + try { + DigitList other = (DigitList) super.clone(); + char[] newDigits = new char[digits.length]; + System.arraycopy(digits, 0, newDigits, 0, digits.length); + other.digits = newDigits; + return other; + } catch (CloneNotSupportedException e) { + throw new InternalError(); + } + } + + /** + * Returns true if this DigitList represents Long.MIN_VALUE; + * false, otherwise. This is required so that getLong() works. + */ + private boolean isLongMIN_VALUE() { + if (decimalAt != count || count != MAX_COUNT) { + return false; + } + + for (int i = 0; i < count; ++i) { + if (digits[i] != LONG_MIN_REP[i]) return false; + } + + return true; + } + + private static final int parseInt(char[] str, int offset, int strLen) { + char c; + boolean positive = true; + if ((c = str[offset]) == '-') { + positive = false; + offset++; + } else if (c == '+') { + offset++; + } + + int value = 0; + while (offset < strLen) { + c = str[offset++]; + if (c >= '0' && c <= '9') { + value = value * 10 + (c - '0'); + } else { + break; + } + } + return positive ? value : -value; + } + + // The digit part of -9223372036854775808L + private static final char[] LONG_MIN_REP = "9223372036854775808".toCharArray(); + + @Override + public String toString() { + if (isZero()) { + return "0"; + } + StringBuffer buf = getStringBuffer(); + buf.append("0."); + buf.append(digits, 0, count); + buf.append("x10^"); + buf.append(decimalAt); + return buf.toString(); + } + + private StringBuffer tempBuffer; + + private StringBuffer getStringBuffer() { + if (tempBuffer == null) { + tempBuffer = new StringBuffer(MAX_COUNT); + } else { + tempBuffer.setLength(0); + } + return tempBuffer; + } + + private void extendDigits(int len) { + if (len > digits.length) { + digits = new char[len]; + } + } + + private final char[] getDataChars(int length) { + if (data == null || data.length < length) { + data = new char[length]; + } + return data; + } +} diff --git a/simplCore/src/ecologylab/generic/text/EfficientDecimalFormat.java b/simplCore/src/ecologylab/generic/text/EfficientDecimalFormat.java index 89c957c9..a732bb38 100644 --- a/simplCore/src/ecologylab/generic/text/EfficientDecimalFormat.java +++ b/simplCore/src/ecologylab/generic/text/EfficientDecimalFormat.java @@ -1,3198 +1,3198 @@ -package ecologylab.generic.text; - -/* - * @(#)DecimalFormat.java 1.79 04/06/28 - * - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -/* - * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved - * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved - * - * The original version of this source code and documentation is copyrighted - * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These - * materials are provided under terms of a License Agreement between Taligent - * and Sun. This technology is protected by multiple US and International - * patents. This notice and attribution to Taligent may not be removed. - * Taligent is a registered trademark of Taligent, Inc. - * - */ -import java.io.IOException; -import java.io.InvalidObjectException; -import java.io.ObjectInputStream; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.text.DecimalFormat; -import java.text.FieldPosition; -import java.text.NumberFormat; -import java.text.ParsePosition; -import java.util.Currency; - -/** - * EfficientDecimalFormat is like the - * {@link java.text.DecimalFormat} class, as described below, except that it: - * - * 1.) will format into an Appendable, to improve efficiency - * - * 2.) emits NaN for not-a-number, rather than ? (as described below). - * - * 3.) DOES NOT USE LOCALES. Due to an undocumented change between the 1.5 and - * 1.6 JREs there is currently no way to support them. Instead, this class (and - * ecologylab.generic.text.DecimalFormatSymbols) will simply use the standard - * characters for the US). - * - * DecimalFormat is a concrete subclass of - * NumberFormat that formats decimal numbers. It has a variety of - * features designed to make it possible to parse and format numbers in any - * locale, including support for Western, Arabic, and Indic digits. It also - * supports different kinds of numbers, including integers (123), fixed-point - * numbers (123.4), scientific notation (1.23E4), percentages (12%), and - * currency amounts ($123). All of these can be localized. - * - *

- * To obtain a NumberFormat for a specific locale, including the - * default locale, call one of NumberFormat's factory methods, - * such as getInstance(). In general, do not call the - * DecimalFormat constructors directly, since the - * NumberFormat factory methods may return subclasses other than - * DecimalFormat. If you need to customize the format object, do - * something like this: - * - *

- * - *
- * NumberFormat f = NumberFormat.getInstance(loc);
- * if (f instanceof DecimalFormat)
- * {
- * 	((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
- * }
- * 
- * - *
- * - *

- * A DecimalFormat comprises a pattern and a set of - * symbols. The pattern may be set directly using - * applyPattern(), or indirectly using the API methods. The - * symbols are stored in a DecimalFormatSymbols object. When - * using the NumberFormat factory methods, the pattern and - * symbols are read from localized ResourceBundles. - * - *

Patterns

- * - * DecimalFormat patterns have the following syntax:
- * - *
- * <i>Pattern:</i>
- *         <i>PositivePattern</i>
- *         <i>PositivePattern</i> ; <i>NegativePattern</i>
- * <i>PositivePattern:</i>
- *         <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
- * <i>NegativePattern:</i>
- *         <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
- * <i>Prefix:</i>
- *         any Unicode characters except \uFFFE, \uFFFF, and special characters
- * <i>Suffix:</i>
- *         any Unicode characters except \uFFFE, \uFFFF, and special characters
- * <i>Number:</i>
- *         <i>Integer</i> <i>Exponent<sub>opt</sub></i>
- *         <i>Integer</i> . <i>Fraction</i> <i>Exponent<sub>opt</sub></i>
- * <i>Integer:</i>
- *         <i>MinimumInteger</i>
- *         #
- *         # <i>Integer</i>
- *         # , <i>Integer</i>
- * <i>MinimumInteger:</i>
- *         0
- *         0 <i>MinimumInteger</i>
- *         0 , <i>MinimumInteger</i>
- * <i>Fraction:</i>
- *         <i>MinimumFraction<sub>opt</sub></i> <i>OptionalFraction<sub>opt</sub></i>
- * <i>MinimumFraction:</i>
- *         0 <i>MinimumFraction<sub>opt</sub></i>
- * <i>OptionalFraction:</i>
- *         # <i>OptionalFraction<sub>opt</sub></i>
- * <i>Exponent:</i>
- *         E <i>MinimumExponent</i>
- * <i>MinimumExponent:</i>
- *         0 <i>MinimumExponent<sub>opt</sub></i>
- * 
- * - *
- * - *

- * A DecimalFormat pattern contains a positive and negative - * subpattern, for example, "#,##0.00;(#,##0.00)". Each - * subpattern has a prefix, numeric part, and suffix. The negative subpattern is - * optional; if absent, then the positive subpattern prefixed with the localized - * minus sign ('-' in most locales) is used as the negative - * subpattern. That is, "0.00" alone is equivalent to - * "0.00;-0.00". If there is an explicit negative subpattern, it - * serves only to specify the negative prefix and suffix; the number of digits, - * minimal digits, and other characteristics are all the same as the positive - * pattern. That means that "#,##0.0#;(#)" produces precisely the - * same behavior as "#,##0.0#;(#,##0.0#)". - * - *

- * The prefixes, suffixes, and various symbols used for infinity, digits, - * thousands separators, decimal separators, etc. may be set to arbitrary - * values, and they will appear properly during formatting. However, care must - * be taken that the symbols and strings do not conflict, or parsing will be - * unreliable. For example, either the positive and negative prefixes or the - * suffixes must be distinct for DecimalFormat.parse() to be able - * to distinguish positive from negative values. (If they are identical, then - * DecimalFormat will behave as if no negative subpattern was - * specified.) Another example is that the decimal separator and thousands - * separator should be distinct characters, or parsing will be impossible. - * - *

- * The grouping separator is commonly used for thousands, but in some countries - * it separates ten-thousands. The grouping size is a constant number of digits - * between the grouping characters, such as 3 for 100,000,000 or 4 for - * 1,0000,0000. If you supply a pattern with multiple grouping characters, the - * interval between the last one and the end of the integer is the one that is - * used. So "#,##,###,####" == "######,####" == - * "##,####,####". - * - *

Special Pattern Characters

- * - *

- * Many characters in a pattern are taken literally; they are matched during - * parsing and output unchanged during formatting. Special characters, on the - * other hand, stand for other characters, strings, or classes of characters. - * They must be quoted, unless noted otherwise, if they are to appear in the - * prefix or suffix as literals. - * - *

- * The characters listed here are used in non-localized patterns. Localized - * patterns use the corresponding characters taken from this formatter's - * DecimalFormatSymbols object instead, and these characters lose - * their special status. Two exceptions are the currency sign and quote, which - * are not localized. - * - *

- * - * - * - * - * - * - * - * - * - * - * - * - *
Symbol - * Location - * Localized? - * Meaning - *
0 - * Number - * Yes - * Digit - *
# - * Number - * Yes - * Digit, zero shows as absent - *
. - * Number - * Yes - * Decimal separator or monetary decimal separator - *
- - * Number - * Yes - * Minus sign - *
, - * Number - * Yes - * Grouping separator - *
E - * Number - * Yes - * Separates mantissa and exponent in scientific notation. - * Need not be quoted in prefix or suffix. - *
; - * Subpattern boundary - * Yes - * Separates positive and negative subpatterns - *
% - * Prefix or suffix - * Yes - * Multiply by 100 and show as percentage - *
\u2030 - * Prefix or suffix - * Yes - * Multiply by 1000 and show as per mille value - *
¤ (\u00A4) - * Prefix or suffix - * No - * Currency sign, replaced by currency symbol. If doubled, replaced by - * international currency symbol. If present in a pattern, the monetary decimal - * separator is used instead of the decimal separator. - *
' - * Prefix or suffix - * No - * Used to quote special characters in a prefix or suffix, for example, - * "'#'#" formats 123 to "#123". To create a - * single quote itself, use two in a row: "# o''clock".
- *
- * - *

Scientific Notation

- * - *

- * Numbers in scientific notation are expressed as the product of a mantissa and - * a power of ten, for example, 1234 can be expressed as 1.234 x 10^3. The - * mantissa is often in the range 1.0 <= x < 10.0, but it need not be. - * DecimalFormat can be instructed to format and parse scientific - * notation only via a pattern; there is currently no factory method - * that creates a scientific notation format. In a pattern, the exponent - * character immediately followed by one or more digit characters indicates - * scientific notation. Example: "0.###E0" formats the number - * 1234 as "1.234E3". - * - *

    - *
  • The number of digit characters after the exponent character gives the - * minimum exponent digit count. There is no maximum. Negative exponents are - * formatted using the localized minus sign, not the prefix and - * suffix from the pattern. This allows patterns such as - * "0.###E0 m/s". - * - *
  • The minimum and maximum number of integer digits are interpreted - * together: - * - *
      - *
    • If the maximum number of integer digits is greater than their minimum - * number and greater than 1, it forces the exponent to be a multiple of the - * maximum number of integer digits, and the minimum number of integer digits to - * be interpreted as 1. The most common use of this is to generate - * engineering notation, in which the exponent is a multiple of - * three, e.g., "##0.#####E0". Using this pattern, the number - * 12345 formats to "12.345E3", and 123456 formats to - * "123.456E3". - * - *
    • Otherwise, the minimum number of integer digits is achieved by adjusting - * the exponent. Example: 0.00123 formatted with "00.###E0" - * yields "12.3E-4". - *
    - * - *
  • The number of significant digits in the mantissa is the sum of the - * minimum integer and maximum fraction digits, and is - * unaffected by the maximum integer digits. For example, 12345 formatted with - * "##0.##E0" is "12.3E3". To show all digits, - * set the significant digits count to zero. The number of significant digits - * does not affect parsing. - * - *
  • Exponential patterns may not contain grouping separators. - *
- * - *

Rounding

- * - * DecimalFormat uses half-even rounding (see - * {@link java.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for - * formatting. - * - *

Digits

- * - * For formatting, DecimalFormat uses the ten consecutive - * characters starting with the localized zero digit defined in the - * DecimalFormatSymbols object as digits. For parsing, these - * digits as well as all Unicode decimal digits, as defined by - * {@link Character#digit Character.digit}, are recognized. - * - *

Special Values

- * - *

- * NaN is formatted as a single character, typically - * \uFFFD. This character is determined by the - * DecimalFormatSymbols object. This is the only value for which - * the prefixes and suffixes are not used. - * - *

- * Infinity is formatted as a single character, typically - * \u221E, with the positive or negative prefixes and - * suffixes applied. The infinity character is determined by the - * DecimalFormatSymbols object. - * - *

- * Negative zero ("-0") parses to - *

    - *
  • BigDecimal(0) if isParseBigDecimal() is - * true, - *
  • Long(0) if isParseBigDecimal() is false - * and isParseIntegerOnly() is true, - *
  • Double(-0.0) if both isParseBigDecimal() - * and isParseIntegerOnly() are false. - *
- * - *

Synchronization

- * - *

- * Decimal formats are generally not synchronized. It is recommended to create - * separate format instances for each thread. If multiple threads access a - * format concurrently, it must be synchronized externally. - * - *

Example

- * - *
- * - *
- * <strong>// Print out a number using the localized number, integer, currency,
- * // and percent format for each locale</strong>
- * Locale[] locales = NumberFormat.getAvailableLocales();
- * double myNumber = -1234.56;
- * NumberFormat form;
- * for (int j=0; j<4; ++j) {
- *     System.out.println("FORMAT");
- *     for (int i = 0; i < locales.length; ++i) {
- *         if (locales[i].getCountry().length() == 0) {
- *            continue; // Skip language-only locales
- *         }
- *         System.out.print(locales[i].getDisplayName());
- *         switch (j) {
- *         case 0:
- *             form = NumberFormat.getInstance(locales[i]); break;
- *         case 1:
- *             form = NumberFormat.getIntegerInstance(locales[i]); break;
- *         case 2:
- *             form = NumberFormat.getCurrencyInstance(locales[i]); break;
- *         default:
- *             form = NumberFormat.getPercentInstance(locales[i]); break;
- *         }
- *         if (form instanceof DecimalFormat) {
- *             System.out.print(": " + ((DecimalFormat) form).toPattern());
- *         }
- *         System.out.print(" -> " + form.format(myNumber));
- *         try {
- *             System.out.println(" -> " + form.parse(form.format(myNumber)));
- *         } catch (ParseException e) {}
- *     }
- * }
- * 
- * - *
- * - * @see Java - * Tutorial - * @see NumberFormat - * @see DecimalFormatSymbols - * @see ParsePosition - * @version 1.79 06/28/04 - * @author Mark Davis - * @author Alan Liu - * @author Zachary O. Toups (toupsz@ecologylab.net) - */ -public class EfficientDecimalFormat extends DecimalFormat -{ - /** - * Creates a DecimalFormat using the given pattern and the symbols for the - * default locale. This is a convenient way to obtain a DecimalFormat when - * internationalization is not the main concern. - *

- * To obtain standard formats for a given locale, use the factory methods on - * NumberFormat such as getNumberInstance. These factories will return the - * most appropriate sub-class of NumberFormat for a given locale. - * - * @param pattern - * A non-localized pattern string. - * @exception NullPointerException - * if pattern is null - * @exception IllegalArgumentException - * if the given pattern is invalid. - * @see java.text.NumberFormat#getInstance - * @see java.text.NumberFormat#getNumberInstance - * @see java.text.NumberFormat#getCurrencyInstance - * @see java.text.NumberFormat#getPercentInstance - */ - public EfficientDecimalFormat(String pattern) - { - // Always applyPattern after the symbols are set - this.symbols = new DecimalFormatSymbols(); - - applyPattern(pattern); - } - - /** - * Creates a DecimalFormat using the given pattern and symbols. Use this - * constructor when you need to completely customize the behavior of the - * format. - *

- * To obtain standard formats for a given locale, use the factory methods on - * NumberFormat such as getInstance or getCurrencyInstance. If you need only - * minor adjustments to a standard format, you can modify the format returned - * by a NumberFormat factory method. - * - * @param pattern - * a non-localized pattern string - * @param symbols - * the set of symbols to be used - * @exception NullPointerException - * if any of the given arguments is null - * @exception IllegalArgumentException - * if the given pattern is invalid - * @see java.text.NumberFormat#getInstance - * @see java.text.NumberFormat#getNumberInstance - * @see java.text.NumberFormat#getCurrencyInstance - * @see java.text.NumberFormat#getPercentInstance - * @see java.text.DecimalFormatSymbols - */ - public EfficientDecimalFormat(String pattern, DecimalFormatSymbols symbols) - { - // Always applyPattern after the symbols are set - this.symbols = (DecimalFormatSymbols) symbols.clone(); - this.symbols.setNaN("NaN"); - - applyPattern(pattern); - } - - // Overrides - /** - * Formats a number and appends the resulting text to the given string - * buffer. The number can be of any subclass of {@link java.lang.Number}. - *

- * This implementation uses the maximum precision permitted. - * - * @param number - * the number to format - * @param toAppendTo - * the StringBuffer to which the formatted text is - * to be appended - * @param pos - * On input: an alignment field, if desired. On output: the offsets - * of the alignment field. - * @return the value passed in as toAppendTo - * @throws IOException - * @exception IllegalArgumentException - * if number is null or not an instance of - * Number. - * @exception NullPointerException - * if toAppendTo or pos is null - * @see java.text.FieldPosition - */ - public final Appendable format(Object number, Appendable toAppendTo) - throws IOException - { - if (number instanceof Long - || number instanceof Integer - || number instanceof Short - || number instanceof Byte - || (number instanceof BigInteger && ((BigInteger) number) - .bitLength() < 64)) - { - return format(((Number) number).longValue(), toAppendTo); - } - else if (number instanceof BigDecimal) - { - return format((BigDecimal) number, toAppendTo); - } - else if (number instanceof BigInteger) - { - return format((BigInteger) number, toAppendTo); - } - else if (number instanceof Number) - { - return format(((Number) number).doubleValue(), toAppendTo); - } - else - { - throw new IllegalArgumentException( - "Cannot format given Object as a Number"); - } - } - - /** - * Formats a double to produce a string. - * - * @param number - * The double to format - * @param result - * where the text is to be appended - * @param delegate - * notified of locations of sub fields - * @return The formatted number string - * @throws IOException - */ - public Appendable format(double number, Appendable result) - throws IOException - { - if (Double.isNaN(number) - || (Double.isInfinite(number) && multiplier == 0)) - { - result.append(symbols.getNaN()); - - return result; - } - - /* - * Detecting whether a double is negative is easy with the exception of - * the value -0.0. This is a double which has a zero mantissa (and - * exponent), but a negative sign bit. It is semantically distinct from a - * zero with a positive sign bit, and this distinction is important to - * certain kinds of computations. However, it's a little tricky to detect, - * since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you may ask, does it - * behave distinctly from +0.0? Well, 1/(-0.0) == -Infinity. Proper - * detection of -0.0 is needed to deal with the issues raised by bugs - * 4106658, 4106667, and 4147706. Liu 7/6/98. - */ - boolean isNegative = ((number < 0.0) || (number == 0.0 && 1 / number < 0.0)) - ^ (multiplier < 0); - - if (multiplier != 1) - { - number *= multiplier; - } - - if (Double.isInfinite(number)) - { - if (isNegative) - { - result.append(negativePrefix); - } - else - { - result.append(positivePrefix); - } - - result.append(symbols.getInfinity()); - - if (isNegative) - { - result.append(negativeSuffix); - } - else - { - result.append(positiveSuffix); - } - - return result; - } - - if (isNegative) - { - number = -number; - } - - // at this point we are guaranteed a nonnegative finite number. - assert (number >= 0 && !Double.isInfinite(number)); - - synchronized (digitList) - { - int maxIntDigits = super.getMaximumIntegerDigits(); - int minIntDigits = super.getMinimumIntegerDigits(); - int maxFraDigits = super.getMaximumFractionDigits(); - int minFraDigits = super.getMinimumFractionDigits(); - - digitList.set(number, useExponentialNotation ? maxIntDigits - + maxFraDigits : maxFraDigits, !useExponentialNotation); - return subformat(result, isNegative, false, maxIntDigits, - minIntDigits, maxFraDigits, minFraDigits); - } - } - - /** - * Format a long to produce a string. - * - * @param number - * The long to format - * @param result - * where the text is to be appended - * @param delegate - * notified of locations of sub fields - * @return The formatted number string - * @throws IOException - * @see java.text.FieldPosition - */ - public Appendable format(long number, Appendable result) throws IOException - { - boolean isNegative = (number < 0); - if (isNegative) - { - number = -number; - } - - // In general, long values always represent real finite numbers, so - // we don't have to check for +/- Infinity or NaN. However, there - // is one case we have to be careful of: The multiplier can push - // a number near MIN_VALUE or MAX_VALUE outside the legal range. We - // check for this before multiplying, and if it happens we use - // BigInteger instead. - boolean useBigInteger = false; - if (number < 0) - { // This can only happen if number == Long.MIN_VALUE. - if (multiplier != 0) - { - useBigInteger = true; - } - } - else if (multiplier != 1 && multiplier != 0) - { - long cutoff = Long.MAX_VALUE / multiplier; - if (cutoff < 0) - { - cutoff = -cutoff; - } - useBigInteger = (number > cutoff); - } - - if (useBigInteger) - { - if (isNegative) - { - number = -number; - } - BigInteger bigIntegerValue = BigInteger.valueOf(number); - return format(bigIntegerValue, result, true); - } - - number *= multiplier; - if (number == 0) - { - isNegative = false; - } - else - { - if (multiplier < 0) - { - number = -number; - isNegative = !isNegative; - } - } - - synchronized (digitList) - { - int maxIntDigits = super.getMaximumIntegerDigits(); - int minIntDigits = super.getMinimumIntegerDigits(); - int maxFraDigits = super.getMaximumFractionDigits(); - int minFraDigits = super.getMinimumFractionDigits(); - - digitList.set(number, useExponentialNotation ? maxIntDigits - + maxFraDigits : 0); - - return subformat(result, isNegative, true, maxIntDigits, minIntDigits, - maxFraDigits, minFraDigits); - } - } - - /** - * Formats a BigDecimal to produce a string. - * - * @param number - * The BigDecimal to format - * @param result - * where the text is to be appended - * @param delegate - * notified of locations of sub fields - * @return The formatted number string - * @throws IOException - */ - public Appendable format(BigDecimal number, Appendable result) - throws IOException - { - if (multiplier != 1) - { - number = number.multiply(getBigDecimalMultiplier()); - } - boolean isNegative = number.signum() == -1; - if (isNegative) - { - number = number.negate(); - } - - synchronized (digitList) - { - int maxIntDigits = getMaximumIntegerDigits(); - int minIntDigits = getMinimumIntegerDigits(); - int maxFraDigits = getMaximumFractionDigits(); - int minFraDigits = getMinimumFractionDigits(); - int maximumDigits = maxIntDigits + maxFraDigits; - - digitList - .set( - number, - useExponentialNotation ? ((maximumDigits < 0) ? Integer.MAX_VALUE - : maximumDigits) - : maxFraDigits, !useExponentialNotation); - - return subformat(result, isNegative, false, maxIntDigits, - minIntDigits, maxFraDigits, minFraDigits); - } - } - - /** - * Format a BigInteger to produce a string. - * - * @param number - * The BigInteger to format - * @param result - * where the text is to be appended - * @param fieldPosition - * On input: an alignment field, if desired. On output: the offsets - * of the alignment field. - * @return The formatted number string - * @throws IOException - * @see java.text.FieldPosition - */ - private Appendable format(BigInteger number, Appendable result) - throws IOException - { - return format(number, result, false); - } - - /** - * Format a BigInteger to produce a string. - * - * @param number - * The BigInteger to format - * @param result - * where the text is to be appended - * @param delegate - * notified of locations of sub fields - * @return The formatted number string - * @throws IOException - * @see java.text.FieldPosition - */ - private Appendable format(BigInteger number, Appendable result, - boolean formatLong) throws IOException - { - if (multiplier != 1) - { - number = number.multiply(getBigIntegerMultiplier()); - } - boolean isNegative = number.signum() == -1; - if (isNegative) - { - number = number.negate(); - } - - synchronized (digitList) - { - int maxIntDigits, minIntDigits, maxFraDigits, minFraDigits, maximumDigits; - if (formatLong) - { - maxIntDigits = super.getMaximumIntegerDigits(); - minIntDigits = super.getMinimumIntegerDigits(); - maxFraDigits = super.getMaximumFractionDigits(); - minFraDigits = super.getMinimumFractionDigits(); - maximumDigits = maxIntDigits + maxFraDigits; - } - else - { - maxIntDigits = getMaximumIntegerDigits(); - minIntDigits = getMinimumIntegerDigits(); - maxFraDigits = getMaximumFractionDigits(); - minFraDigits = getMinimumFractionDigits(); - maximumDigits = maxIntDigits + maxFraDigits; - if (maximumDigits < 0) - { - maximumDigits = Integer.MAX_VALUE; - } - } - - digitList.set(number, useExponentialNotation ? maximumDigits : 0); - - return subformat(result, isNegative, true, maxIntDigits, minIntDigits, - maxFraDigits, minFraDigits); - } - } - - /** - * Complete the formatting of a finite number. On entry, the digitList must - * be filled in with the correct digits. - * - * @throws IOException - */ - private Appendable subformat(Appendable result, boolean isNegative, - boolean isInteger, int maxIntDigits, int minIntDigits, - int maxFraDigits, int minFraDigits) throws IOException - { - char zero = symbols.getZeroDigit(); - int zeroDelta = zero - '0'; // '0' is the DigitList representation of - // zero - char grouping = symbols.getGroupingSeparator(); - char decimal = isCurrencyFormat ? symbols.getMonetaryDecimalSeparator() - : symbols.getDecimalSeparator(); - - /* - * Per bug 4147706, DecimalFormat must respect the sign of numbers which - * format as zero. This allows sensible computations and preserves - * relations such as signum(1/x) = signum(x), where x is +Infinity or - * -Infinity. Prior to this fix, we always formatted zero values as if - * they were positive. Liu 7/6/98. - */ - if (digitList.isZero()) - digitList.decimalAt = 0; // Normalize - - if (isNegative) - result.append(negativePrefix); - else - result.append(positivePrefix); - - if (useExponentialNotation) - { - int iFieldEnd = -1; - int fFieldStart = -1; - - // Minimum integer digits are handled in exponential format by - // adjusting the exponent. For example, 0.01234 with 3 minimum - // integer digits is "123.4E-4". - - // Maximum integer digits are interpreted as indicating the - // repeating range. This is useful for engineering notation, in - // which the exponent is restricted to a multiple of 3. For - // example, 0.01234 with 3 maximum integer digits is "12.34e-3". - // If maximum integer digits are > 1 and are larger than - // minimum integer digits, then minimum integer digits are - // ignored. - int exponent = digitList.decimalAt; - int repeat = maxIntDigits; - if (repeat > 1 && repeat > minIntDigits) - { - // A repeating range is defined; adjust to it as follows. - // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3; - // -3,-4,-5=>-6, etc. This takes into account that the - // exponent we have here is off by one from what we expect; - // it is for the format 0.MMMMMx10^n. - if (exponent >= 1) - { - exponent = ((exponent - 1) / repeat) * repeat; - } - else - { - // integer division rounds towards 0 - exponent = ((exponent - repeat) / repeat) * repeat; - } - minimumIntegerDigits = 1; - } - else - { - // No repeating range is defined; use minimum integer digits. - exponent -= minimumIntegerDigits; - } - - // We now output a minimum number of digits, and more if there - // are more digits, up to the maximum number of digits. We - // place the decimal point after the "integer" digits, which - // are the first (decimalAt - exponent) digits. - int minimumDigits = minIntDigits + minFraDigits; - if (minimumDigits < 0) - { // overflow? - minimumDigits = Integer.MAX_VALUE; - } - - // The number of integer digits is handled specially if the number - // is zero, since then there may be no digits. - int integerDigits = digitList.isZero() ? minimumIntegerDigits - : digitList.decimalAt - exponent; - if (minimumDigits < integerDigits) - { - minimumDigits = integerDigits; - } - int totalDigits = digitList.count; - if (minimumDigits > totalDigits) - { - totalDigits = minimumDigits; - } - boolean addedDecimalSeparator = false; - - for (int i = 0; i < totalDigits; ++i) - { - if (i == integerDigits) - { - result.append(decimal); - addedDecimalSeparator = true; - } - result - .append((i < digitList.count) ? (char) (digitList.digits[i] + zeroDelta) - : zero); - } - - if (decimalSeparatorAlwaysShown && totalDigits == integerDigits) - { - result.append(decimal); - addedDecimalSeparator = true; - } - - // The exponent is output using the pattern-specified minimum - // exponent digits. There is no maximum limit to the exponent - // digits, since truncating the exponent would result in an - // unacceptable inaccuracy. - - result.append(symbols.getExponentialSymbol()); - - // For zero values, we force the exponent to zero. We - // must do this here, and not earlier, because the value - // is used to determine integer digit count above. - if (digitList.isZero()) - { - exponent = 0; - } - - boolean negativeExponent = exponent < 0; - if (negativeExponent) - { - exponent = -exponent; - result.append(symbols.getMinusSign()); - } - digitList.set(exponent); - - for (int i = digitList.decimalAt; i < minExponentDigits; ++i) - { - result.append(zero); - } - for (int i = 0; i < digitList.decimalAt; ++i) - { - result - .append((i < digitList.count) ? (char) (digitList.digits[i] + zeroDelta) - : zero); - } - } - else - { - // Output the integer portion. Here 'count' is the total - // number of integer digits we will display, including both - // leading zeros required to satisfy getMinimumIntegerDigits, - // and actual digits present in the number. - int count = minIntDigits; - int digitIndex = 0; // Index into digitList.fDigits[] - if (digitList.decimalAt > 0 && count < digitList.decimalAt) - { - count = digitList.decimalAt; - } - - // Handle the case where getMaximumIntegerDigits() is smaller - // than the real number of integer digits. If this is so, we - // output the least significant max integer digits. For example, - // the value 1997 printed with 2 max integer digits is just "97". - if (count > maxIntDigits) - { - count = maxIntDigits; - digitIndex = digitList.decimalAt - count; - } - - // indicate whether or not any characters have been appended before the - // fraction part - boolean actuallyAppended = (count - 1 < 0); - for (int i = count - 1; i >= 0; --i) - { - if (i < digitList.decimalAt && digitIndex < digitList.count) - { - // Output a real digit - result - .append((char) (digitList.digits[digitIndex++] + zeroDelta)); - - } - else - { - // Output a leading zero - result.append(zero); - } - - // Output grouping separator if necessary. Don't output a - // grouping separator if i==0 though; that's at the end of - // the integer part. - if (isGroupingUsed() && i > 0 && (groupingSize != 0) - && (i % groupingSize == 0)) - { - result.append(grouping); - } - } - - // Determine whether or not there are any printable fractional - // digits. If we've used up the digits we know there aren't. - boolean fractionPresent = (minFraDigits > 0) - || (!isInteger && digitIndex < digitList.count); - - // If there is no fraction present, and we haven't printed any - // integer digits, then print a zero. Otherwise we won't print - // _any_ digits, and we won't be able to parse this string. - if (!fractionPresent && actuallyAppended) - { - result.append(zero); - } - - // Output the decimal separator if we always do so. - if (decimalSeparatorAlwaysShown || fractionPresent) - { - result.append(decimal); - } - - for (int i = 0; i < maxFraDigits; ++i) - { - // Here is where we escape from the loop. We escape if we've - // output the maximum fraction digits (specified in the for - // expression above). - // We also stop when we've output the minimum digits and either: - // we have an integer, so there is no fractional stuff to - // display, or we're out of significant digits. - if (i >= minFraDigits - && (isInteger || digitIndex >= digitList.count)) - { - break; - } - - // Output leading fractional zeros. These are zeros that come - // after the decimal but before any significant digits. These - // are only output if abs(number being formatted) < 1.0. - if (-1 - i > (digitList.decimalAt - 1)) - { - result.append(zero); - continue; - } - - // Output a digit, if we have any precision left, or a - // zero if we don't. We don't want to output noise digits. - if (!isInteger && digitIndex < digitList.count) - { - result - .append((char) (digitList.digits[digitIndex++] + zeroDelta)); - } - else - { - result.append(zero); - } - } - } - - if (isNegative) - result.append(negativeSuffix); - else - result.append(positiveSuffix); - - return result; - } - - /** - * Parses text from a string to produce a Number. - *

- * The method attempts to parse text starting at the index given by - * pos. If parsing succeeds, then the index of - * pos is updated to the index after the last character used - * (parsing does not necessarily use all characters up to the end of the - * string), and the parsed number is returned. The updated pos - * can be used to indicate the starting point for the next call to this - * method. If an error occurs, then the index of pos is not - * changed, the error index of pos is set to the index of the - * character where the error occurred, and null is returned. - *

- * The subclass returned depends on the value of {@link #isParseBigDecimal} - * as well as on the string being parsed. - *

    - *
  • If isParseBigDecimal() is false (the default), most - * integer values are returned as Long objects, no matter how - * they are written: "17" and "17.000" both - * parse to Long(17). Values that cannot fit into a - * Long are returned as Doubles. This includes - * values with a fractional part, infinite values, NaN, and - * the value -0.0. DecimalFormat does not decide - * whether to return a Double or a Long based - * on the presence of a decimal separator in the source string. Doing so - * would prevent integers that overflow the mantissa of a double, such as - * "-9,223,372,036,854,775,808.00", from being parsed - * accurately. - *

    - * Callers may use the Number methods doubleValue, - * longValue, etc., to obtain the type they want. - *

  • If isParseBigDecimal() is true, values are returned as - * BigDecimal objects. The values are the ones constructed by - * {@link java.math.BigDecimal#BigDecimal(String)} for corresponding strings - * in locale-independent format. The special cases negative and positive - * infinity and NaN are returned as Double instances holding - * the values of the corresponding Double constants. - *
- *

- * DecimalFormat parses all Unicode characters that represent - * decimal digits, as defined by Character.digit(). In - * addition, DecimalFormat also recognizes as digits the ten - * consecutive characters starting with the localized zero digit defined in - * the DecimalFormatSymbols object. - * - * @param text - * the string to be parsed - * @param pos - * A ParsePosition object with index and error index - * information as described above. - * @return the parsed value, or null if the parse fails - * @exception NullPointerException - * if text or pos is null. - */ - @Override - public Number parse(String text, ParsePosition pos) - { - // special case NaN - if (text.regionMatches(pos.getIndex(), symbols.getNaN(), 0, symbols - .getNaN().length())) - { - pos.setIndex(pos.getIndex() + symbols.getNaN().length()); - return new Double(Double.NaN); - } - - boolean[] status = new boolean[STATUS_LENGTH]; - if (!subparse(text, pos, positivePrefix, negativePrefix, digitList, - false, status)) - { - return null; - } - - // special case INFINITY - if (status[STATUS_INFINITE]) - { - if (status[STATUS_POSITIVE] == (multiplier >= 0)) - { - return new Double(Double.POSITIVE_INFINITY); - } - else - { - return new Double(Double.NEGATIVE_INFINITY); - } - } - - if (multiplier == 0) - { - if (digitList.isZero()) - { - return new Double(Double.NaN); - } - else if (status[STATUS_POSITIVE]) - { - return new Double(Double.POSITIVE_INFINITY); - } - else - { - return new Double(Double.NEGATIVE_INFINITY); - } - } - - if (isParseBigDecimal()) - { - BigDecimal bigDecimalResult = digitList.getBigDecimal(); - - if (multiplier != 1) - { - try - { - bigDecimalResult = bigDecimalResult - .divide(getBigDecimalMultiplier()); - } - catch (ArithmeticException e) - { // non-terminating decimal expansion - bigDecimalResult = bigDecimalResult.divide( - getBigDecimalMultiplier(), BigDecimal.ROUND_HALF_EVEN); - } - } - - if (!status[STATUS_POSITIVE]) - { - bigDecimalResult = bigDecimalResult.negate(); - } - return bigDecimalResult; - } - else - { - boolean gotDouble = true; - boolean gotLongMinimum = false; - double doubleResult = 0.0; - long longResult = 0; - - // Finally, have DigitList parse the digits into a value. - if (digitList.fitsIntoLong(status[STATUS_POSITIVE], - isParseIntegerOnly())) - { - gotDouble = false; - longResult = digitList.getLong(); - if (longResult < 0) - { // got Long.MIN_VALUE - gotLongMinimum = true; - } - } - else - { - doubleResult = digitList.getDouble(); - } - - // Divide by multiplier. We have to be careful here not to do - // unneeded conversions between double and long. - if (multiplier != 1) - { - if (gotDouble) - { - doubleResult /= multiplier; - } - else - { - // Avoid converting to double if we can - if (longResult % multiplier == 0) - { - longResult /= multiplier; - } - else - { - doubleResult = ((double) longResult) / multiplier; - gotDouble = true; - } - } - } - - if (!status[STATUS_POSITIVE] && !gotLongMinimum) - { - doubleResult = -doubleResult; - longResult = -longResult; - } - - // At this point, if we divided the result by the multiplier, the - // result may fit into a long. We check for this case and return - // a long if possible. - // We must do this AFTER applying the negative (if appropriate) - // in order to handle the case of LONG_MIN; otherwise, if we do - // this with a positive value -LONG_MIN, the double is > 0, but - // the long is < 0. We also must retain a double in the case of - // -0.0, which will compare as == to a long 0 cast to a double - // (bug 4162852). - if (multiplier != 1 && gotDouble) - { - longResult = (long) doubleResult; - gotDouble = ((doubleResult != longResult) || (doubleResult == 0.0 && 1 / doubleResult < 0.0)) - && !isParseIntegerOnly(); - } - - return gotDouble ? (Number) new Double(doubleResult) - : (Number) new Long(longResult); - } - } - - /** - * Return a BigInteger multiplier. - */ - private BigInteger getBigIntegerMultiplier() - { - if (bigIntegerMultiplier == null) - { - bigIntegerMultiplier = BigInteger.valueOf(multiplier); - } - return bigIntegerMultiplier; - } - - private transient BigInteger bigIntegerMultiplier; - - /** - * Return a BigDecimal multiplier. - */ - private BigDecimal getBigDecimalMultiplier() - { - if (bigDecimalMultiplier == null) - { - bigDecimalMultiplier = new BigDecimal(multiplier); - } - return bigDecimalMultiplier; - } - - private transient BigDecimal bigDecimalMultiplier; - - private static final int STATUS_INFINITE = 0; - - private static final int STATUS_POSITIVE = 1; - - private static final int STATUS_LENGTH = 2; - - /** - * Parse the given text into a number. The text is parsed beginning at - * parsePosition, until an unparseable character is seen. - * - * @param text - * The string to parse. - * @param parsePosition - * The position at which to being parsing. Upon return, the first - * unparseable character. - * @param digits - * The DigitList to set to the parsed value. - * @param isExponent - * If true, parse an exponent. This means no infinite values and - * integer only. - * @param status - * Upon return contains boolean status flags indicating whether the - * value was infinite and whether it was positive. - */ - private final boolean subparse(String text, ParsePosition parsePosition, - String positivePrefix, String negativePrefix, DigitList digits, - boolean isExponent, boolean status[]) - { - int position = parsePosition.getIndex(); - int oldStart = parsePosition.getIndex(); - int backup; - boolean gotPositive, gotNegative; - - // check for positivePrefix; take longest - gotPositive = text.regionMatches(position, positivePrefix, 0, - positivePrefix.length()); - gotNegative = text.regionMatches(position, negativePrefix, 0, - negativePrefix.length()); - - if (gotPositive && gotNegative) - { - if (positivePrefix.length() > negativePrefix.length()) - { - gotNegative = false; - } - else if (positivePrefix.length() < negativePrefix.length()) - { - gotPositive = false; - } - } - - if (gotPositive) - { - position += positivePrefix.length(); - } - else if (gotNegative) - { - position += negativePrefix.length(); - } - else - { - parsePosition.setErrorIndex(position); - return false; - } - - // process digits or Inf, find decimal position - status[STATUS_INFINITE] = false; - if (!isExponent - && text.regionMatches(position, symbols.getInfinity(), 0, symbols - .getInfinity().length())) - { - position += symbols.getInfinity().length(); - status[STATUS_INFINITE] = true; - } - else - { - // We now have a string of digits, possibly with grouping symbols, - // and decimal points. We want to process these into a DigitList. - // We don't want to put a bunch of leading zeros into the DigitList - // though, so we keep track of the location of the decimal point, - // put only significant digits into the DigitList, and adjust the - // exponent as needed. - - digits.decimalAt = digits.count = 0; - char zero = symbols.getZeroDigit(); - char decimal = isCurrencyFormat ? symbols - .getMonetaryDecimalSeparator() : symbols.getDecimalSeparator(); - char grouping = symbols.getGroupingSeparator(); - char exponentChar = symbols.getExponentialSymbol(); - boolean sawDecimal = false; - boolean sawExponent = false; - boolean sawDigit = false; - int exponent = 0; // Set to the exponent value, if any - - // We have to track digitCount ourselves, because digits.count will - // pin when the maximum allowable digits is reached. - int digitCount = 0; - - backup = -1; - for (; position < text.length(); ++position) - { - char ch = text.charAt(position); - - /* - * We recognize all digit ranges, not only the Latin digit range - * '0'..'9'. We do so by using the Character.digit() method, which - * converts a valid Unicode digit to the range 0..9. - * - * The character 'ch' may be a digit. If so, place its value from 0 - * to 9 in 'digit'. First try using the locale digit, which may or - * MAY NOT be a standard Unicode digit range. If this fails, try - * using the standard Unicode digit ranges by calling - * Character.digit(). If this also fails, digit will have a value - * outside the range 0..9. - */ - int digit = ch - zero; - if (digit < 0 || digit > 9) - { - digit = Character.digit(ch, 10); - } - - if (digit == 0) - { - // Cancel out backup setting (see grouping handler below) - backup = -1; // Do this BEFORE continue statement below!!! - sawDigit = true; - - // Handle leading zeros - if (digits.count == 0) - { - // Ignore leading zeros in integer part of number. - if (!sawDecimal) - { - continue; - } - - // If we have seen the decimal, but no significant - // digits yet, then we account for leading zeros by - // decrementing the digits.decimalAt into negative - // values. - --digits.decimalAt; - } - else - { - ++digitCount; - digits.append((char) (digit + '0')); - } - } - else if (digit > 0 && digit <= 9) - { // [sic] digit==0 handled above - sawDigit = true; - ++digitCount; - digits.append((char) (digit + '0')); - - // Cancel out backup setting (see grouping handler below) - backup = -1; - } - else if (!isExponent && ch == decimal) - { - // If we're only parsing integers, or if we ALREADY saw the - // decimal, then don't parse this one. - if (isParseIntegerOnly() || sawDecimal) - { - break; - } - digits.decimalAt = digitCount; // Not digits.count! - sawDecimal = true; - } - else if (!isExponent && ch == grouping && isGroupingUsed()) - { - if (sawDecimal) - { - break; - } - // Ignore grouping characters, if we are using them, but - // require that they be followed by a digit. Otherwise - // we backup and reprocess them. - backup = position; - } - else if (!isExponent && ch == exponentChar && !sawExponent) - { - // Process the exponent by recursively calling this method. - ParsePosition pos = new ParsePosition(position + 1); - boolean[] stat = new boolean[STATUS_LENGTH]; - DigitList exponentDigits = new DigitList(); - - if (subparse(text, pos, "", Character.toString(symbols - .getMinusSign()), exponentDigits, true, stat) - && exponentDigits - .fitsIntoLong(stat[STATUS_POSITIVE], true)) - { - position = pos.getIndex(); // Advance past the exponent - exponent = (int) exponentDigits.getLong(); - if (!stat[STATUS_POSITIVE]) - { - exponent = -exponent; - } - sawExponent = true; - } - break; // Whether we fail or succeed, we exit this loop - } - else - { - break; - } - } - - if (backup != -1) - { - position = backup; - } - - // If there was no decimal point we have an integer - if (!sawDecimal) - { - digits.decimalAt = digitCount; // Not digits.count! - } - - // Adjust for exponent, if any - digits.decimalAt += exponent; - - // If none of the text string was recognized. For example, parse - // "x" with pattern "#0.00" (return index and error index both 0) - // parse "$" with pattern "$#0.00". (return index 0 and error - // index 1). - if (!sawDigit && digitCount == 0) - { - parsePosition.setIndex(oldStart); - parsePosition.setErrorIndex(oldStart); - return false; - } - } - - // check for suffix - if (!isExponent) - { - if (gotPositive) - { - gotPositive = text.regionMatches(position, positiveSuffix, 0, - positiveSuffix.length()); - } - if (gotNegative) - { - gotNegative = text.regionMatches(position, negativeSuffix, 0, - negativeSuffix.length()); - } - - // if both match, take longest - if (gotPositive && gotNegative) - { - if (positiveSuffix.length() > negativeSuffix.length()) - { - gotNegative = false; - } - else if (positiveSuffix.length() < negativeSuffix.length()) - { - gotPositive = false; - } - } - - // fail if neither or both - if (gotPositive == gotNegative) - { - parsePosition.setErrorIndex(position); - return false; - } - - parsePosition.setIndex(position - + (gotPositive ? positiveSuffix.length() : negativeSuffix - .length())); // mark success! - } - else - { - parsePosition.setIndex(position); - } - - status[STATUS_POSITIVE] = gotPositive; - if (parsePosition.getIndex() == oldStart) - { - parsePosition.setErrorIndex(position); - return false; - } - return true; - } - - /** - * Sets the decimal format symbols, which is generally not changed by the - * programmer or user. - * - * @param newSymbols - * desired DecimalFormatSymbols - * @see java.text.DecimalFormatSymbols - */ - public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) - { - try - { - // don't allow multiple references - symbols = (DecimalFormatSymbols) newSymbols.clone(); - expandAffixes(); - } - catch (Exception foo) - { - // should never happen - } - } - - /** - * Get the positive prefix. - *

- * Examples: +123, $123, sFr123 - */ - @Override public String getPositivePrefix() - { - return positivePrefix; - } - - /** - * Set the positive prefix. - *

- * Examples: +123, $123, sFr123 - */ - @Override public void setPositivePrefix(String newValue) - { - positivePrefix = newValue; - posPrefixPattern = null; - positivePrefixFieldPositions = null; - } - - /** - * Get the negative prefix. - *

- * Examples: -123, ($123) (with negative suffix), sFr-123 - */ - @Override public String getNegativePrefix() - { - return negativePrefix; - } - - /** - * Set the negative prefix. - *

- * Examples: -123, ($123) (with negative suffix), sFr-123 - */ - @Override public void setNegativePrefix(String newValue) - { - negativePrefix = newValue; - negPrefixPattern = null; - } - - /** - * Get the positive suffix. - *

- * Example: 123% - */ - @Override public String getPositiveSuffix() - { - return positiveSuffix; - } - - /** - * Set the positive suffix. - *

- * Example: 123% - */ - @Override public void setPositiveSuffix(String newValue) - { - positiveSuffix = newValue; - posSuffixPattern = null; - } - - /** - * Get the negative suffix. - *

- * Examples: -123%, ($123) (with positive suffixes) - */ - @Override public String getNegativeSuffix() - { - return negativeSuffix; - } - - /** - * Set the negative suffix. - *

- * Examples: 123% - */ - @Override public void setNegativeSuffix(String newValue) - { - negativeSuffix = newValue; - negSuffixPattern = null; - } - - /** - * Gets the multiplier for use in percent, per mille, and similar formats. - * - * @see #setMultiplier(int) - */ - @Override public int getMultiplier() - { - return multiplier; - } - - /** - * Sets the multiplier for use in percent, per mille, and similar formats. - * For a percent format, set the multiplier to 100 and the suffixes to have - * '%' (for Arabic, use the Arabic percent sign). For a per mille format, set - * the multiplier to 1000 and the suffixes to have '\u2030'. - * - *

- * Example: with multiplier 100, 1.23 is formatted as "123", and "123" is - * parsed into 1.23. - * - * @see #getMultiplier - */ - @Override public void setMultiplier(int newValue) - { - multiplier = newValue; - bigDecimalMultiplier = null; - bigIntegerMultiplier = null; - } - - /** - * Return the grouping size. Grouping size is the number of digits between - * grouping separators in the integer portion of a number. For example, in - * the number "123,456.78", the grouping size is 3. - * - * @see #setGroupingSize - * @see java.text.NumberFormat#isGroupingUsed - * @see java.text.DecimalFormatSymbols#getGroupingSeparator - */ - @Override public int getGroupingSize() - { - return groupingSize; - } - - /** - * Set the grouping size. Grouping size is the number of digits between - * grouping separators in the integer portion of a number. For example, in - * the number "123,456.78", the grouping size is 3.
- * The value passed in is converted to a byte, which may lose information. - * - * @see #getGroupingSize - * @see java.text.NumberFormat#setGroupingUsed - * @see java.text.DecimalFormatSymbols#setGroupingSeparator - */ - @Override public void setGroupingSize(int newValue) - { - groupingSize = (byte) newValue; - } - - /** - * Allows you to get the behavior of the decimal separator with integers. - * (The decimal separator will always appear with decimals.) - *

- * Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345 - */ - @Override public boolean isDecimalSeparatorAlwaysShown() - { - return decimalSeparatorAlwaysShown; - } - - /** - * Allows you to set the behavior of the decimal separator with integers. - * (The decimal separator will always appear with decimals.) - *

- * Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345 - */ - @Override public void setDecimalSeparatorAlwaysShown(boolean newValue) - { - decimalSeparatorAlwaysShown = newValue; - } - - /** - * Returns whether the - * {@link #parse(java.lang.String, java.text.ParsePosition)} method returns - * BigDecimal. The default value is false. - * - * @see #setParseBigDecimal - * @since 1.5 - */ - @Override public boolean isParseBigDecimal() - { - return parseBigDecimal; - } - - /** - * Sets whether the {@link #parse(java.lang.String, java.text.ParsePosition)} - * method returns BigDecimal. - * - * @see #isParseBigDecimal - * @since 1.5 - */ - @Override public void setParseBigDecimal(boolean newValue) - { - parseBigDecimal = newValue; - } - - /** - * Standard override; no change in semantics. - */ - @Override public Object clone() - { - try - { - EfficientDecimalFormat other = (EfficientDecimalFormat) super.clone(); - other.symbols = (DecimalFormatSymbols) symbols.clone(); - other.digitList = (DigitList) digitList.clone(); - return other; - } - catch (Exception e) - { - throw new InternalError(); - } - } - - /** - * Overrides equals - */ - @Override public boolean equals(Object obj) - { - if (obj == null) - return false; - if (!super.equals(obj)) - return false; // super does class check - EfficientDecimalFormat other = (EfficientDecimalFormat) obj; - return ((posPrefixPattern == other.posPrefixPattern && positivePrefix - .equals(other.positivePrefix)) || (posPrefixPattern != null && posPrefixPattern - .equals(other.posPrefixPattern))) - && ((posSuffixPattern == other.posSuffixPattern && positiveSuffix - .equals(other.positiveSuffix)) || (posSuffixPattern != null && posSuffixPattern - .equals(other.posSuffixPattern))) - && ((negPrefixPattern == other.negPrefixPattern && negativePrefix - .equals(other.negativePrefix)) || (negPrefixPattern != null && negPrefixPattern - .equals(other.negPrefixPattern))) - && ((negSuffixPattern == other.negSuffixPattern && negativeSuffix - .equals(other.negativeSuffix)) || (negSuffixPattern != null && negSuffixPattern - .equals(other.negSuffixPattern))) - && multiplier == other.multiplier - && groupingSize == other.groupingSize - && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown - && parseBigDecimal == other.parseBigDecimal - && useExponentialNotation == other.useExponentialNotation - && (!useExponentialNotation || minExponentDigits == other.minExponentDigits) - && maximumIntegerDigits == other.maximumIntegerDigits - && minimumIntegerDigits == other.minimumIntegerDigits - && maximumFractionDigits == other.maximumFractionDigits - && minimumFractionDigits == other.minimumFractionDigits - && symbols.equals(other.symbols); - } - - /** - * Overrides hashCode - */ - @Override public int hashCode() - { - return super.hashCode() * 37 + positivePrefix.hashCode(); - // just enough fields for a reasonable distribution - } - - /** - * Synthesizes a pattern string that represents the current state of this - * Format object. - * - * @see #applyPattern - */ - @Override public String toPattern() - { - return toPattern(false); - } - - /** - * Synthesizes a localized pattern string that represents the current state - * of this Format object. - * - * @see #applyPattern - */ - @Override public String toLocalizedPattern() - { - return toPattern(true); - } - - /** - * Expand the affix pattern strings into the expanded affix strings. If any - * affix pattern string is null, do not expand it. This method should be - * called any time the symbols or the affix patterns change in order to keep - * the expanded affix strings up to date. - */ - private void expandAffixes() - { - // Reuse one StringBuffer for better performance - StringBuffer buffer = new StringBuffer(); - if (posPrefixPattern != null) - { - positivePrefix = expandAffix(posPrefixPattern, buffer); - positivePrefixFieldPositions = null; - } - if (posSuffixPattern != null) - { - positiveSuffix = expandAffix(posSuffixPattern, buffer); - positiveSuffixFieldPositions = null; - } - if (negPrefixPattern != null) - { - negativePrefix = expandAffix(negPrefixPattern, buffer); - negativePrefixFieldPositions = null; - } - if (negSuffixPattern != null) - { - negativeSuffix = expandAffix(negSuffixPattern, buffer); - negativeSuffixFieldPositions = null; - } - } - - /** - * Expand an affix pattern into an affix string. All characters in the - * pattern are literal unless prefixed by QUOTE. The following characters - * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, - * PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE + - * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217 currency - * code. Any other character after a QUOTE represents itself. QUOTE must be - * followed by another character; QUOTE may not occur by itself at the end of - * the pattern. - * - * @param pattern - * the non-null, possibly empty pattern - * @param buffer - * a scratch StringBuffer; its contents will be lost - * @return the expanded equivalent of pattern - */ - private String expandAffix(String pattern, StringBuffer buffer) - { - buffer.setLength(0); - for (int i = 0; i < pattern.length();) - { - char c = pattern.charAt(i++); - if (c == QUOTE) - { - c = pattern.charAt(i++); - switch (c) - { - case CURRENCY_SIGN: - if (i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN) - { - ++i; - buffer.append(symbols.getInternationalCurrencySymbol()); - } - else - { - buffer.append(symbols.getCurrencySymbol()); - } - continue; - case PATTERN_PERCENT: - c = symbols.getPercent(); - break; - case PATTERN_PER_MILLE: - c = symbols.getPerMill(); - break; - case PATTERN_MINUS: - c = symbols.getMinusSign(); - break; - } - } - buffer.append(c); - } - return buffer.toString(); - } - - /** - * Appends an affix pattern to the given StringBuffer, quoting special - * characters as needed. Uses the internal affix pattern, if that exists, or - * the literal affix, if the internal affix pattern is null. The appended - * string will generate the same affix pattern (or literal affix) when passed - * to toPattern(). - * - * @param buffer - * the affix string is appended to this - * @param affixPattern - * a pattern such as posPrefixPattern; may be null - * @param expAffix - * a corresponding expanded affix, such as positivePrefix. Ignored - * unless affixPattern is null. If affixPattern is null, then - * expAffix is appended as a literal affix. - * @param localized - * true if the appended pattern should contain localized pattern - * characters; otherwise, non-localized pattern chars are appended - */ - private void appendAffix(StringBuffer buffer, String affixPattern, - String expAffix, boolean localized) - { - if (affixPattern == null) - { - appendAffix(buffer, expAffix, localized); - } - else - { - int i; - for (int pos = 0; pos < affixPattern.length(); pos = i) - { - i = affixPattern.indexOf(QUOTE, pos); - if (i < 0) - { - appendAffix(buffer, affixPattern.substring(pos), localized); - break; - } - if (i > pos) - { - appendAffix(buffer, affixPattern.substring(pos, i), localized); - } - char c = affixPattern.charAt(++i); - ++i; - if (c == QUOTE) - { - buffer.append(c); - // Fall through and append another QUOTE below - } - else if (c == CURRENCY_SIGN && i < affixPattern.length() - && affixPattern.charAt(i) == CURRENCY_SIGN) - { - ++i; - buffer.append(c); - // Fall through and append another CURRENCY_SIGN below - } - else if (localized) - { - switch (c) - { - case PATTERN_PERCENT: - c = symbols.getPercent(); - break; - case PATTERN_PER_MILLE: - c = symbols.getPerMill(); - break; - case PATTERN_MINUS: - c = symbols.getMinusSign(); - break; - } - } - buffer.append(c); - } - } - } - - /** - * Append an affix to the given StringBuffer, using quotes if there are - * special characters. Single quotes themselves must be escaped in either - * case. - */ - private void appendAffix(StringBuffer buffer, String affix, boolean localized) - { - boolean needQuote; - if (localized) - { - needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0 - || affix.indexOf(symbols.getGroupingSeparator()) >= 0 - || affix.indexOf(symbols.getDecimalSeparator()) >= 0 - || affix.indexOf(symbols.getPercent()) >= 0 - || affix.indexOf(symbols.getPerMill()) >= 0 - || affix.indexOf(symbols.getDigit()) >= 0 - || affix.indexOf(symbols.getPatternSeparator()) >= 0 - || affix.indexOf(symbols.getMinusSign()) >= 0 - || affix.indexOf(CURRENCY_SIGN) >= 0; - } - else - { - needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0 - || affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 0 - || affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 0 - || affix.indexOf(PATTERN_PERCENT) >= 0 - || affix.indexOf(PATTERN_PER_MILLE) >= 0 - || affix.indexOf(PATTERN_DIGIT) >= 0 - || affix.indexOf(PATTERN_SEPARATOR) >= 0 - || affix.indexOf(PATTERN_MINUS) >= 0 - || affix.indexOf(CURRENCY_SIGN) >= 0; - } - if (needQuote) - buffer.append('\''); - if (affix.indexOf('\'') < 0) - buffer.append(affix); - else - { - for (int j = 0; j < affix.length(); ++j) - { - char c = affix.charAt(j); - buffer.append(c); - if (c == '\'') - buffer.append(c); - } - } - if (needQuote) - buffer.append('\''); - } - - /** - * Does the real work of generating a pattern. - */ - private String toPattern(boolean localized) - { - StringBuffer result = new StringBuffer(); - for (int j = 1; j >= 0; --j) - { - if (j == 1) - appendAffix(result, posPrefixPattern, positivePrefix, localized); - else - appendAffix(result, negPrefixPattern, negativePrefix, localized); - int i; - int digitCount = useExponentialNotation ? getMaximumIntegerDigits() - : Math.max(groupingSize, getMinimumIntegerDigits()) + 1; - for (i = digitCount; i > 0; --i) - { - if (i != digitCount && isGroupingUsed() && groupingSize != 0 - && i % groupingSize == 0) - { - result.append(localized ? symbols.getGroupingSeparator() - : PATTERN_GROUPING_SEPARATOR); - } - result.append(i <= getMinimumIntegerDigits() ? (localized ? symbols - .getZeroDigit() : PATTERN_ZERO_DIGIT) : (localized ? symbols - .getDigit() : PATTERN_DIGIT)); - } - if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) - result.append(localized ? symbols.getDecimalSeparator() - : PATTERN_DECIMAL_SEPARATOR); - for (i = 0; i < getMaximumFractionDigits(); ++i) - { - if (i < getMinimumFractionDigits()) - { - result.append(localized ? symbols.getZeroDigit() - : PATTERN_ZERO_DIGIT); - } - else - { - result.append(localized ? symbols.getDigit() : PATTERN_DIGIT); - } - } - if (useExponentialNotation) - { - result.append(localized ? symbols.getExponentialSymbol() - : PATTERN_EXPONENT); - for (i = 0; i < minExponentDigits; ++i) - result.append(localized ? symbols.getZeroDigit() - : PATTERN_ZERO_DIGIT); - } - if (j == 1) - { - appendAffix(result, posSuffixPattern, positiveSuffix, localized); - if ((negSuffixPattern == posSuffixPattern && // n == p == null - negativeSuffix.equals(positiveSuffix)) - || (negSuffixPattern != null && negSuffixPattern - .equals(posSuffixPattern))) - { - if ((negPrefixPattern != null && posPrefixPattern != null && negPrefixPattern - .equals("'-" + posPrefixPattern)) - || (negPrefixPattern == posPrefixPattern && // n == p == - // null - negativePrefix.equals(symbols.getMinusSign() - + positivePrefix))) - break; - } - result.append(localized ? symbols.getPatternSeparator() - : PATTERN_SEPARATOR); - } - else - appendAffix(result, negSuffixPattern, negativeSuffix, localized); - } - return result.toString(); - } - - /** - * Apply the given pattern to this Format object. The pattern is assumed to - * be in a localized notation. A pattern is a short-hand specification for - * the various formatting properties. These properties can also be changed - * individually through the various setter methods. - *

- * There is no limit to integer digits are set by this routine, since that is - * the typical end-user desire; use setMaximumInteger if you want to set a - * real value. For negative numbers, use a second pattern, separated by a - * semicolon - *

- * Example "#,#00.0#" -> 1,234.56 - *

- * This means a minimum of 2 integer digits, 1 fraction digit, and a maximum - * of 2 fraction digits. - *

- * Example: "#,#00.0#;(#,#00.0#)" for negatives in - * parentheses. - *

- * In negative patterns, the minimum and maximum counts are ignored; these - * are presumed to be set in the positive pattern. - * - * @exception NullPointerException - * if pattern is null - * @exception IllegalArgumentException - * if the given pattern is invalid. - */ - @Override public void applyLocalizedPattern(String pattern) - { - applyPattern(pattern); - } - - /** - * Does the real work of applying a pattern. - */ - @Override public void applyPattern(String pattern) - { - char zeroDigit = PATTERN_ZERO_DIGIT; - char groupingSeparator = PATTERN_GROUPING_SEPARATOR; - char decimalSeparator = PATTERN_DECIMAL_SEPARATOR; - char percent = PATTERN_PERCENT; - char perMill = PATTERN_PER_MILLE; - char digit = PATTERN_DIGIT; - char separator = PATTERN_SEPARATOR; - char exponent = PATTERN_EXPONENT; - char minus = PATTERN_MINUS; - - zeroDigit = symbols.getZeroDigit(); - groupingSeparator = symbols.getGroupingSeparator(); - decimalSeparator = symbols.getDecimalSeparator(); - percent = symbols.getPercent(); - perMill = symbols.getPerMill(); - digit = symbols.getDigit(); - separator = symbols.getPatternSeparator(); - exponent = symbols.getExponentialSymbol(); - minus = symbols.getMinusSign(); - - boolean gotNegative = false; - decimalSeparatorAlwaysShown = false; - isCurrencyFormat = false; - useExponentialNotation = false; - - // Two variables are used to record the subrange of the pattern - // occupied by phase 1. This is used during the processing of the - // second pattern (the one representing negative numbers) to ensure - // that no deviation exists in phase 1 between the two patterns. - int phaseOneStart = 0; - int phaseOneLength = 0; - - int start = 0; - for (int j = 1; j >= 0 && start < pattern.length(); --j) - { - boolean inQuote = false; - StringBuffer prefix = new StringBuffer(); - StringBuffer suffix = new StringBuffer(); - int decimalPos = -1; - int multiplier = 1; - int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0; - byte groupingCount = -1; - - // The phase ranges from 0 to 2. Phase 0 is the prefix. Phase 1 is - // the section of the pattern with digits, decimal separator, - // grouping characters. Phase 2 is the suffix. In phases 0 and 2, - // percent, per mille, and currency symbols are recognized and - // translated. The separation of the characters into phases is - // strictly enforced; if phase 1 characters are to appear in the - // suffix, for example, they must be quoted. - int phase = 0; - - // The affix is either the prefix or the suffix. - StringBuffer affix = prefix; - - for (int pos = start; pos < pattern.length(); ++pos) - { - char ch = pattern.charAt(pos); - switch (phase) - { - case 0: - case 2: - // Process the prefix / suffix characters - if (inQuote) - { - // A quote within quotes indicates either the closing - // quote or two quotes, which is a quote literal. That - // is, we have the second quote in 'do' or 'don''t'. - if (ch == QUOTE) - { - if ((pos + 1) < pattern.length() - && pattern.charAt(pos + 1) == QUOTE) - { - ++pos; - affix.append("''"); // 'don''t' - } - else - { - inQuote = false; // 'do' - } - continue; - } - } - else - { - // Process unquoted characters seen in prefix or suffix - // phase. - if (ch == digit || ch == zeroDigit || ch == groupingSeparator - || ch == decimalSeparator) - { - phase = 1; - if (j == 1) - { - phaseOneStart = pos; - } - --pos; // Reprocess this character - continue; - } - else if (ch == CURRENCY_SIGN) - { - // Use lookahead to determine if the currency sign - // is doubled or not. - boolean doubled = (pos + 1) < pattern.length() - && pattern.charAt(pos + 1) == CURRENCY_SIGN; - if (doubled) - { // Skip over the doubled character - ++pos; - } - isCurrencyFormat = true; - affix.append(doubled ? "'\u00A4\u00A4" : "'\u00A4"); - continue; - } - else if (ch == QUOTE) - { - // A quote outside quotes indicates either the - // opening quote or two quotes, which is a quote - // literal. That is, we have the first quote in 'do' - // or o''clock. - if (ch == QUOTE) - { - if ((pos + 1) < pattern.length() - && pattern.charAt(pos + 1) == QUOTE) - { - ++pos; - affix.append("''"); // o''clock - } - else - { - inQuote = true; // 'do' - } - continue; - } - } - else if (ch == separator) - { - // Don't allow separators before we see digit - // characters of phase 1, and don't allow separators - // in the second pattern (j == 0). - if (phase == 0 || j == 0) - { - throw new IllegalArgumentException( - "Unquoted special character '" + ch - + "' in pattern \"" + pattern + '"'); - } - start = pos + 1; - pos = pattern.length(); - continue; - } - - // Next handle characters which are appended directly. - else if (ch == percent) - { - if (multiplier != 1) - { - throw new IllegalArgumentException( - "Too many percent/per mille characters in pattern \"" - + pattern + '"'); - } - multiplier = 100; - affix.append("'%"); - continue; - } - else if (ch == perMill) - { - if (multiplier != 1) - { - throw new IllegalArgumentException( - "Too many percent/per mille characters in pattern \"" - + pattern + '"'); - } - multiplier = 1000; - affix.append("'\u2030"); - continue; - } - else if (ch == minus) - { - affix.append("'-"); - continue; - } - } - // Note that if we are within quotes, or if this is an - // unquoted, non-special character, then we usually fall - // through to here. - affix.append(ch); - break; - - case 1: - // Phase one must be identical in the two sub-patterns. We - // enforce this by doing a direct comparison. While - // processing the first sub-pattern, we just record its - // length. While processing the second, we compare - // characters. - if (j == 1) - { - ++phaseOneLength; - } - else - { - if (--phaseOneLength == 0) - { - phase = 2; - affix = suffix; - } - continue; - } - - // Process the digits, decimal, and grouping characters. We - // record five pieces of information. We expect the digits - // to occur in the pattern ####0000.####, and we record the - // number of left digits, zero (central) digits, and right - // digits. The position of the last grouping character is - // recorded (should be somewhere within the first two blocks - // of characters), as is the position of the decimal point, - // if any (should be in the zero digits). If there is no - // decimal point, then there should be no right digits. - if (ch == digit) - { - if (zeroDigitCount > 0) - { - ++digitRightCount; - } - else - { - ++digitLeftCount; - } - if (groupingCount >= 0 && decimalPos < 0) - { - ++groupingCount; - } - } - else if (ch == zeroDigit) - { - if (digitRightCount > 0) - { - throw new IllegalArgumentException( - "Unexpected '0' in pattern \"" + pattern + '"'); - } - ++zeroDigitCount; - if (groupingCount >= 0 && decimalPos < 0) - { - ++groupingCount; - } - } - else if (ch == groupingSeparator) - { - groupingCount = 0; - } - else if (ch == decimalSeparator) - { - if (decimalPos >= 0) - { - throw new IllegalArgumentException( - "Multiple decimal separators in pattern \"" - + pattern + '"'); - } - decimalPos = digitLeftCount + zeroDigitCount - + digitRightCount; - } - else if (ch == exponent) - { - if (useExponentialNotation) - { - throw new IllegalArgumentException("Multiple exponential " - + "symbols in pattern \"" + pattern + '"'); - } - useExponentialNotation = true; - minExponentDigits = 0; - - // Use lookahead to parse out the exponential part - // of the pattern, then jump into phase 2. - while (++pos < pattern.length() - && pattern.charAt(pos) == zeroDigit) - { - ++minExponentDigits; - ++phaseOneLength; - } - - if ((digitLeftCount + zeroDigitCount) < 1 - || minExponentDigits < 1) - { - throw new IllegalArgumentException( - "Malformed exponential " + "pattern \"" + pattern - + '"'); - } - - // Transition to phase 2 - phase = 2; - affix = suffix; - --pos; - continue; - } - else - { - phase = 2; - affix = suffix; - --pos; - --phaseOneLength; - continue; - } - break; - } - } - - // Handle patterns with no '0' pattern character. These patterns - // are legal, but must be interpreted. "##.###" -> "#0.###". - // ".###" -> ".0##". - /* - * We allow patterns of the form "####" to produce a zeroDigitCount of - * zero (got that?); although this seems like it might make it possible - * for format() to produce empty strings, format() checks for this - * condition and outputs a zero digit in this situation. Having a - * zeroDigitCount of zero yields a minimum integer digits of zero, - * which allows proper round-trip patterns. That is, we don't want "#" - * to become "#0" when toPattern() is called (even though that's what - * it really is, semantically). - */ - if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) - { - // Handle "###.###" and "###." and ".###" - int n = decimalPos; - if (n == 0) - { // Handle ".###" - ++n; - } - digitRightCount = digitLeftCount - n; - digitLeftCount = n - 1; - zeroDigitCount = 1; - } - - // Do syntax checking on the digits. - if ((decimalPos < 0 && digitRightCount > 0) - || (decimalPos >= 0 && (decimalPos < digitLeftCount || decimalPos > (digitLeftCount + zeroDigitCount))) - || groupingCount == 0 || inQuote) - { - throw new IllegalArgumentException("Malformed pattern \"" + pattern - + '"'); - } - - if (j == 1) - { - posPrefixPattern = prefix.toString(); - posSuffixPattern = suffix.toString(); - negPrefixPattern = posPrefixPattern; // assume these for now - negSuffixPattern = posSuffixPattern; - int digitTotalCount = digitLeftCount + zeroDigitCount - + digitRightCount; - /* - * The effectiveDecimalPos is the position the decimal is at or - * would be at if there is no decimal. Note that if decimalPos<0, - * then digitTotalCount == digitLeftCount + zeroDigitCount. - */ - int effectiveDecimalPos = decimalPos >= 0 ? decimalPos - : digitTotalCount; - setMinimumIntegerDigits(effectiveDecimalPos - digitLeftCount); - setMaximumIntegerDigits(useExponentialNotation ? digitLeftCount - + getMinimumIntegerDigits() : MAXIMUM_INTEGER_DIGITS); - setMaximumFractionDigits(decimalPos >= 0 ? (digitTotalCount - decimalPos) - : 0); - setMinimumFractionDigits(decimalPos >= 0 ? (digitLeftCount - + zeroDigitCount - decimalPos) : 0); - setGroupingUsed(groupingCount > 0); - this.groupingSize = (groupingCount > 0) ? groupingCount : 0; - this.multiplier = multiplier; - setDecimalSeparatorAlwaysShown(decimalPos == 0 - || decimalPos == digitTotalCount); - } - else - { - negPrefixPattern = prefix.toString(); - negSuffixPattern = suffix.toString(); - gotNegative = true; - } - } - - if (pattern.length() == 0) - { - posPrefixPattern = posSuffixPattern = ""; - setMinimumIntegerDigits(0); - setMaximumIntegerDigits(MAXIMUM_INTEGER_DIGITS); - setMinimumFractionDigits(0); - setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS); - } - - // If there was no negative pattern, or if the negative pattern is - // identical to the positive pattern, then prepend the minus sign to - // the positive pattern to form the negative pattern. - if (!gotNegative - || (negPrefixPattern.equals(posPrefixPattern) && negSuffixPattern - .equals(posSuffixPattern))) - { - negSuffixPattern = posSuffixPattern; - negPrefixPattern = "'-" + posPrefixPattern; - } - - expandAffixes(); - } - - /** - * Sets the maximum number of digits allowed in the integer portion of a - * number. For formatting numbers other than BigInteger and - * BigDecimal objects, the lower of newValue - * and 309 is used. Negative input values are replaced with 0. - * - * @see NumberFormat#setMaximumIntegerDigits - */ - @Override - public void setMaximumIntegerDigits(int newValue) - { - maximumIntegerDigits = Math.min(Math.max(0, newValue), - MAXIMUM_INTEGER_DIGITS); - super - .setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? DOUBLE_INTEGER_DIGITS - : maximumIntegerDigits); - if (minimumIntegerDigits > maximumIntegerDigits) - { - minimumIntegerDigits = maximumIntegerDigits; - super - .setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? DOUBLE_INTEGER_DIGITS - : minimumIntegerDigits); - } - } - - /** - * Sets the minimum number of digits allowed in the integer portion of a - * number. For formatting numbers other than BigInteger and - * BigDecimal objects, the lower of newValue - * and 309 is used. Negative input values are replaced with 0. - * - * @see NumberFormat#setMinimumIntegerDigits - */ - @Override public void setMinimumIntegerDigits(int newValue) - { - minimumIntegerDigits = Math.min(Math.max(0, newValue), - MAXIMUM_INTEGER_DIGITS); - super - .setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? DOUBLE_INTEGER_DIGITS - : minimumIntegerDigits); - if (minimumIntegerDigits > maximumIntegerDigits) - { - maximumIntegerDigits = minimumIntegerDigits; - super - .setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? DOUBLE_INTEGER_DIGITS - : maximumIntegerDigits); - } - } - - /** - * Sets the maximum number of digits allowed in the fraction portion of a - * number. For formatting numbers other than BigInteger and - * BigDecimal objects, the lower of newValue - * and 340 is used. Negative input values are replaced with 0. - * - * @see NumberFormat#setMaximumFractionDigits - */ - @Override public void setMaximumFractionDigits(int newValue) - { - maximumFractionDigits = Math.min(Math.max(0, newValue), - MAXIMUM_FRACTION_DIGITS); - super - .setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ? DOUBLE_FRACTION_DIGITS - : maximumFractionDigits); - if (minimumFractionDigits > maximumFractionDigits) - { - minimumFractionDigits = maximumFractionDigits; - super - .setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ? DOUBLE_FRACTION_DIGITS - : minimumFractionDigits); - } - } - - /** - * Sets the minimum number of digits allowed in the fraction portion of a - * number. For formatting numbers other than BigInteger and - * BigDecimal objects, the lower of newValue - * and 340 is used. Negative input values are replaced with 0. - * - * @see NumberFormat#setMinimumFractionDigits - */ - @Override public void setMinimumFractionDigits(int newValue) - { - minimumFractionDigits = Math.min(Math.max(0, newValue), - MAXIMUM_FRACTION_DIGITS); - super - .setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ? DOUBLE_FRACTION_DIGITS - : minimumFractionDigits); - if (minimumFractionDigits > maximumFractionDigits) - { - maximumFractionDigits = minimumFractionDigits; - super - .setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ? DOUBLE_FRACTION_DIGITS - : maximumFractionDigits); - } - } - - /** - * Gets the maximum number of digits allowed in the integer portion of a - * number. For formatting numbers other than BigInteger and - * BigDecimal objects, the lower of the return value and 309 - * is used. - * - * @see #setMaximumIntegerDigits - */ - @Override public int getMaximumIntegerDigits() - { - return maximumIntegerDigits; - } - - /** - * Gets the minimum number of digits allowed in the integer portion of a - * number. For formatting numbers other than BigInteger and - * BigDecimal objects, the lower of the return value and 309 - * is used. - * - * @see #setMinimumIntegerDigits - */ - @Override public int getMinimumIntegerDigits() - { - return minimumIntegerDigits; - } - - /** - * Gets the maximum number of digits allowed in the fraction portion of a - * number. For formatting numbers other than BigInteger and - * BigDecimal objects, the lower of the return value and 340 - * is used. - * - * @see #setMaximumFractionDigits - */ - @Override public int getMaximumFractionDigits() - { - return maximumFractionDigits; - } - - /** - * Gets the minimum number of digits allowed in the fraction portion of a - * number. For formatting numbers other than BigInteger and - * BigDecimal objects, the lower of the return value and 340 - * is used. - * - * @see #setMinimumFractionDigits - */ - @Override public int getMinimumFractionDigits() - { - return minimumFractionDigits; - } - - /** - * Gets the currency used by this decimal format when formatting currency - * values. The currency is obtained by calling - * {@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency} - * on this number format's symbols. - * - * @return the currency used by this decimal format, or null - * @since 1.4 - */ - @Override public Currency getCurrency() - { - return symbols.getCurrency(); - } - - /** - * Adjusts the minimum and maximum fraction digits to values that are - * reasonable for the currency's default fraction digits. - */ - void adjustForCurrencyDefaultFractionDigits() - { - Currency currency = symbols.getCurrency(); - if (currency == null) - { - try - { - currency = Currency.getInstance(symbols - .getInternationalCurrencySymbol()); - } - catch (IllegalArgumentException e) - { - } - } - if (currency != null) - { - int digits = currency.getDefaultFractionDigits(); - if (digits != -1) - { - int oldMinDigits = getMinimumFractionDigits(); - // Common patterns are "#.##", "#.00", "#". - // Try to adjust all of them in a reasonable way. - if (oldMinDigits == getMaximumFractionDigits()) - { - setMinimumFractionDigits(digits); - setMaximumFractionDigits(digits); - } - else - { - setMinimumFractionDigits(Math.min(digits, oldMinDigits)); - setMaximumFractionDigits(digits); - } - } - } - } - - /** - * Reads the default serializable fields from the stream and performs - * validations and adjustments for older serialized versions. The validations - * and adjustments are: - *

    - *
  1. Verify that the superclass's digit count fields correctly reflect the - * limits imposed on formatting numbers other than BigInteger - * and BigDecimal objects. These limits are stored in the - * superclass for serialization compatibility with older versions, while the - * limits for BigInteger and BigDecimal objects - * are kept in this class. If, in the superclass, the minimum or maximum - * integer digit count is larger than DOUBLE_INTEGER_DIGITS or - * if the minimum or maximum fraction digit count is larger than - * DOUBLE_FRACTION_DIGITS, then the stream data is invalid - * and this method throws an InvalidObjectException. - *
  2. If serialVersionOnStream is less than 3, then call the - * setters for the minimum and maximum integer and fraction digits with the - * values of the corresponding superclass getters to initialize the fields in - * this class. The fields in this class are new with version 3. - *
  3. If serialVersionOnStream is less than 1, indicating - * that the stream was written by JDK 1.1, initialize - * useExponentialNotation to false, since it was not present - * in JDK 1.1. - *
  4. Set serialVersionOnStream to the maximum allowed value - * so that default serialization will work properly if this object is - * streamed out again. - *
- * - *

- * Stream versions older than 2 will not have the affix pattern variables - * posPrefixPattern etc. As a result, they will be initialized - * to null, which means the affix strings will be taken as - * literal values. This is exactly what we want, since that corresponds to - * the pre-version-2 behavior. - */ - private void readObject(ObjectInputStream stream) throws IOException, - ClassNotFoundException - { - stream.defaultReadObject(); - - // We only need to check the maximum counts because NumberFormat - // .readObject has already ensured that the maximum is greater than the - // minimum count. - if (super.getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS - || super.getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) - { - throw new InvalidObjectException("Digit count out of range"); - } - if (serialVersionOnStream < 3) - { - setMaximumIntegerDigits(super.getMaximumIntegerDigits()); - setMinimumIntegerDigits(super.getMinimumIntegerDigits()); - setMaximumFractionDigits(super.getMaximumFractionDigits()); - setMinimumFractionDigits(super.getMinimumFractionDigits()); - } - if (serialVersionOnStream < 1) - { - // Didn't have exponential fields - useExponentialNotation = false; - } - serialVersionOnStream = currentSerialVersion; - digitList = new DigitList(); - } - - // ---------------------------------------------------------------------- - // INSTANCE VARIABLES - // ---------------------------------------------------------------------- - - private transient DigitList digitList = new DigitList(); - - /** - * The symbol used as a prefix when formatting positive numbers, e.g. "+". - * - * @serial - * @see #getPositivePrefix - */ - private String positivePrefix = ""; - - /** - * The symbol used as a suffix when formatting positive numbers. This is - * often an empty string. - * - * @serial - * @see #getPositiveSuffix - */ - private String positiveSuffix = ""; - - /** - * The symbol used as a prefix when formatting negative numbers, e.g. "-". - * - * @serial - * @see #getNegativePrefix - */ - private String negativePrefix = "-"; - - /** - * The symbol used as a suffix when formatting negative numbers. This is - * often an empty string. - * - * @serial - * @see #getNegativeSuffix - */ - private String negativeSuffix = ""; - - /** - * The prefix pattern for non-negative numbers. This variable corresponds to - * positivePrefix. - * - *

- * This pattern is expanded by the method expandAffix() to - * positivePrefix to update the latter to reflect changes in - * symbols. If this variable is null then - * positivePrefix is taken as a literal value that does not - * change when symbols changes. This variable is always - * null for DecimalFormat objects older than - * stream version 2 restored from stream. - * - * @serial - * @since 1.3 - */ - private String posPrefixPattern; - - /** - * The suffix pattern for non-negative numbers. This variable corresponds to - * positiveSuffix. This variable is analogous to - * posPrefixPattern; see that variable for further - * documentation. - * - * @serial - * @since 1.3 - */ - private String posSuffixPattern; - - /** - * The prefix pattern for negative numbers. This variable corresponds to - * negativePrefix. This variable is analogous to - * posPrefixPattern; see that variable for further - * documentation. - * - * @serial - * @since 1.3 - */ - private String negPrefixPattern; - - /** - * The suffix pattern for negative numbers. This variable corresponds to - * negativeSuffix. This variable is analogous to - * posPrefixPattern; see that variable for further - * documentation. - * - * @serial - * @since 1.3 - */ - private String negSuffixPattern; - - /** - * The multiplier for use in percent, per mille, etc. - * - * @serial - * @see #getMultiplier - */ - private int multiplier = 1; - - /** - * The number of digits between grouping separators in the integer portion of - * a number. Must be greater than 0 if NumberFormat.groupingUsed - * is true. - * - * @serial - * @see #getGroupingSize - * @see java.text.NumberFormat#isGroupingUsed - */ - private byte groupingSize = 3; // invariant, - - // > 0 - // if - // useThousands - - /** - * If true, forces the decimal separator to always appear in a formatted - * number, even if the fractional part of the number is zero. - * - * @serial - * @see #isDecimalSeparatorAlwaysShown - */ - private boolean decimalSeparatorAlwaysShown = false; - - /** - * If true, parse returns BigDecimal wherever possible. - * - * @serial - * @see #isParseBigDecimal - * @since 1.5 - */ - private boolean parseBigDecimal = false; - - /** - * True if this object represents a currency format. This determines whether - * the monetary decimal separator is used instead of the normal one. - */ - private transient boolean isCurrencyFormat = false; - - /** - * The DecimalFormatSymbols object used by this format. It - * contains the symbols used to format numbers, e.g. the grouping separator, - * decimal separator, and so on. - * - * @serial - * @see #setDecimalFormatSymbols - * @see java.text.DecimalFormatSymbols - */ - private DecimalFormatSymbols symbols = null; // LIU - - // new - // DecimalFormatSymbols(); - - /** - * True to force the use of exponential (i.e. scientific) notation when - * formatting numbers. - * - * @serial - * @since 1.2 - */ - private boolean useExponentialNotation; // Newly - - // persistent - // in - // the - // Java - // 2 - // platform - - /** - * FieldPositions describing the positive prefix String. This is lazily - * created. Use getPositivePrefixFieldPositions when needed. - */ - private transient FieldPosition[] positivePrefixFieldPositions; - - /** - * FieldPositions describing the positive suffix String. This is lazily - * created. Use getPositiveSuffixFieldPositions when needed. - */ - private transient FieldPosition[] positiveSuffixFieldPositions; - - /** - * FieldPositions describing the negative prefix String. This is lazily - * created. Use getNegativePrefixFieldPositions when needed. - */ - private transient FieldPosition[] negativePrefixFieldPositions; - - /** - * FieldPositions describing the negative suffix String. This is lazily - * created. Use getNegativeSuffixFieldPositions when needed. - */ - private transient FieldPosition[] negativeSuffixFieldPositions; - - /** - * The minimum number of digits used to display the exponent when a number is - * formatted in exponential notation. This field is ignored if - * useExponentialNotation is not true. - * - * @serial - * @since 1.2 - */ - private byte minExponentDigits; // Newly - - // persistent - // in - // the - // Java - // 2 - // platform - - /** - * The maximum number of digits allowed in the integer portion of a - * BigInteger or BigDecimal number. - * maximumIntegerDigits must be greater than or equal to - * minimumIntegerDigits. - * - * @serial - * @see #getMaximumIntegerDigits - * @since 1.5 - */ - private int maximumIntegerDigits = super - .getMaximumIntegerDigits(); - - /** - * The minimum number of digits allowed in the integer portion of a - * BigInteger or BigDecimal number. - * minimumIntegerDigits must be less than or equal to - * maximumIntegerDigits. - * - * @serial - * @see #getMinimumIntegerDigits - * @since 1.5 - */ - private int minimumIntegerDigits = super - .getMinimumIntegerDigits(); - - /** - * The maximum number of digits allowed in the fractional portion of a - * BigInteger or BigDecimal number. - * maximumFractionDigits must be greater than or equal to - * minimumFractionDigits. - * - * @serial - * @see #getMaximumFractionDigits - * @since 1.5 - */ - private int maximumFractionDigits = super - .getMaximumFractionDigits(); - - /** - * The minimum number of digits allowed in the fractional portion of a - * BigInteger or BigDecimal number. - * minimumFractionDigits must be less than or equal to - * maximumFractionDigits. - * - * @serial - * @see #getMinimumFractionDigits - * @since 1.5 - */ - private int minimumFractionDigits = super - .getMinimumFractionDigits(); - - // ---------------------------------------------------------------------- - - static final int currentSerialVersion = 3; - - /** - * The internal serial version which says which version was written. Possible - * values are: - *

    - *
  • 0 (default): versions before the Java 2 platform v1.2 - *
  • 1: version for 1.2, which includes the two new fields - * useExponentialNotation and minExponentDigits. - *
  • 2: version for 1.3 and later, which adds four new fields: - * posPrefixPattern, posSuffixPattern, - * negPrefixPattern, and negSuffixPattern. - *
  • 3: version for 5 and later, which adds five new fields: - * maximumIntegerDigits, minimumIntegerDigits, - * maximumFractionDigits, minimumFractionDigits, - * and parseBigDecimal. - *
- * - * @since 1.2 - * @serial - */ - private int serialVersionOnStream = currentSerialVersion; - - // ---------------------------------------------------------------------- - // CONSTANTS - // ---------------------------------------------------------------------- - - // Constants for characters used in programmatic (unlocalized) patterns. - private static final char PATTERN_ZERO_DIGIT = '0'; - - private static final char PATTERN_GROUPING_SEPARATOR = ','; - - private static final char PATTERN_DECIMAL_SEPARATOR = '.'; - - private static final char PATTERN_PER_MILLE = '\u2030'; - - private static final char PATTERN_PERCENT = '%'; - - private static final char PATTERN_DIGIT = '#'; - - private static final char PATTERN_SEPARATOR = ';'; - - private static final char PATTERN_EXPONENT = 'E'; - - private static final char PATTERN_MINUS = '-'; - - /** - * The CURRENCY_SIGN is the standard Unicode symbol for currency. It is used - * in patterns and substituted with either the currency symbol, or if it is - * doubled, with the international currency symbol. If the CURRENCY_SIGN is - * seen in a pattern, then the decimal separator is replaced with the - * monetary decimal separator. - * - * The CURRENCY_SIGN is not localized. - */ - private static final char CURRENCY_SIGN = '\u00A4'; - - private static final char QUOTE = '\''; - - private static FieldPosition[] EmptyFieldPositionArray = new FieldPosition[0]; - - // Upper limit on integer and fraction digits for a Java double - static final int DOUBLE_INTEGER_DIGITS = 309; - - static final int DOUBLE_FRACTION_DIGITS = 340; - - // Upper limit on integer and fraction digits for BigDecimal and BigInteger - static final int MAXIMUM_INTEGER_DIGITS = Integer.MAX_VALUE; - - static final int MAXIMUM_FRACTION_DIGITS = Integer.MAX_VALUE; - - // Proclaim JDK 1.1 serial compatibility. - static final long serialVersionUID = 864413376551465018L; -} +package ecologylab.generic.text; + +/* + * @(#)DecimalFormat.java 1.79 04/06/28 + * + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +/* + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved + * + * The original version of this source code and documentation is copyrighted + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These + * materials are provided under terms of a License Agreement between Taligent + * and Sun. This technology is protected by multiple US and International + * patents. This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + */ +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.DecimalFormat; +import java.text.FieldPosition; +import java.text.NumberFormat; +import java.text.ParsePosition; +import java.util.Currency; + +/** + * EfficientDecimalFormat is like the + * {@link java.text.DecimalFormat} class, as described below, except that it: + * + * 1.) will format into an Appendable, to improve efficiency + * + * 2.) emits NaN for not-a-number, rather than ? (as described below). + * + * 3.) DOES NOT USE LOCALES. Due to an undocumented change between the 1.5 and + * 1.6 JREs there is currently no way to support them. Instead, this class (and + * ecologylab.generic.text.DecimalFormatSymbols) will simply use the standard + * characters for the US). + * + * DecimalFormat is a concrete subclass of + * NumberFormat that formats decimal numbers. It has a variety of + * features designed to make it possible to parse and format numbers in any + * locale, including support for Western, Arabic, and Indic digits. It also + * supports different kinds of numbers, including integers (123), fixed-point + * numbers (123.4), scientific notation (1.23E4), percentages (12%), and + * currency amounts ($123). All of these can be localized. + * + *

+ * To obtain a NumberFormat for a specific locale, including the + * default locale, call one of NumberFormat's factory methods, + * such as getInstance(). In general, do not call the + * DecimalFormat constructors directly, since the + * NumberFormat factory methods may return subclasses other than + * DecimalFormat. If you need to customize the format object, do + * something like this: + * + *

+ * + *
+ * NumberFormat f = NumberFormat.getInstance(loc);
+ * if (f instanceof DecimalFormat)
+ * {
+ * 	((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
+ * }
+ * 
+ * + *
+ * + *

+ * A DecimalFormat comprises a pattern and a set of + * symbols. The pattern may be set directly using + * applyPattern(), or indirectly using the API methods. The + * symbols are stored in a DecimalFormatSymbols object. When + * using the NumberFormat factory methods, the pattern and + * symbols are read from localized ResourceBundles. + * + *

Patterns

+ * + * DecimalFormat patterns have the following syntax:
+ * + *
+ * <i>Pattern:</i>
+ *         <i>PositivePattern</i>
+ *         <i>PositivePattern</i> ; <i>NegativePattern</i>
+ * <i>PositivePattern:</i>
+ *         <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
+ * <i>NegativePattern:</i>
+ *         <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
+ * <i>Prefix:</i>
+ *         any Unicode characters except \uFFFE, \uFFFF, and special characters
+ * <i>Suffix:</i>
+ *         any Unicode characters except \uFFFE, \uFFFF, and special characters
+ * <i>Number:</i>
+ *         <i>Integer</i> <i>Exponent<sub>opt</sub></i>
+ *         <i>Integer</i> . <i>Fraction</i> <i>Exponent<sub>opt</sub></i>
+ * <i>Integer:</i>
+ *         <i>MinimumInteger</i>
+ *         #
+ *         # <i>Integer</i>
+ *         # , <i>Integer</i>
+ * <i>MinimumInteger:</i>
+ *         0
+ *         0 <i>MinimumInteger</i>
+ *         0 , <i>MinimumInteger</i>
+ * <i>Fraction:</i>
+ *         <i>MinimumFraction<sub>opt</sub></i> <i>OptionalFraction<sub>opt</sub></i>
+ * <i>MinimumFraction:</i>
+ *         0 <i>MinimumFraction<sub>opt</sub></i>
+ * <i>OptionalFraction:</i>
+ *         # <i>OptionalFraction<sub>opt</sub></i>
+ * <i>Exponent:</i>
+ *         E <i>MinimumExponent</i>
+ * <i>MinimumExponent:</i>
+ *         0 <i>MinimumExponent<sub>opt</sub></i>
+ * 
+ * + *
+ * + *

+ * A DecimalFormat pattern contains a positive and negative + * subpattern, for example, "#,##0.00;(#,##0.00)". Each + * subpattern has a prefix, numeric part, and suffix. The negative subpattern is + * optional; if absent, then the positive subpattern prefixed with the localized + * minus sign ('-' in most locales) is used as the negative + * subpattern. That is, "0.00" alone is equivalent to + * "0.00;-0.00". If there is an explicit negative subpattern, it + * serves only to specify the negative prefix and suffix; the number of digits, + * minimal digits, and other characteristics are all the same as the positive + * pattern. That means that "#,##0.0#;(#)" produces precisely the + * same behavior as "#,##0.0#;(#,##0.0#)". + * + *

+ * The prefixes, suffixes, and various symbols used for infinity, digits, + * thousands separators, decimal separators, etc. may be set to arbitrary + * values, and they will appear properly during formatting. However, care must + * be taken that the symbols and strings do not conflict, or parsing will be + * unreliable. For example, either the positive and negative prefixes or the + * suffixes must be distinct for DecimalFormat.parse() to be able + * to distinguish positive from negative values. (If they are identical, then + * DecimalFormat will behave as if no negative subpattern was + * specified.) Another example is that the decimal separator and thousands + * separator should be distinct characters, or parsing will be impossible. + * + *

+ * The grouping separator is commonly used for thousands, but in some countries + * it separates ten-thousands. The grouping size is a constant number of digits + * between the grouping characters, such as 3 for 100,000,000 or 4 for + * 1,0000,0000. If you supply a pattern with multiple grouping characters, the + * interval between the last one and the end of the integer is the one that is + * used. So "#,##,###,####" == "######,####" == + * "##,####,####". + * + *

Special Pattern Characters

+ * + *

+ * Many characters in a pattern are taken literally; they are matched during + * parsing and output unchanged during formatting. Special characters, on the + * other hand, stand for other characters, strings, or classes of characters. + * They must be quoted, unless noted otherwise, if they are to appear in the + * prefix or suffix as literals. + * + *

+ * The characters listed here are used in non-localized patterns. Localized + * patterns use the corresponding characters taken from this formatter's + * DecimalFormatSymbols object instead, and these characters lose + * their special status. Two exceptions are the currency sign and quote, which + * are not localized. + * + *

+ * + * + * + * + * + * + * + * + * + * + * + * + *
Symbol + * Location + * Localized? + * Meaning + *
0 + * Number + * Yes + * Digit + *
# + * Number + * Yes + * Digit, zero shows as absent + *
. + * Number + * Yes + * Decimal separator or monetary decimal separator + *
- + * Number + * Yes + * Minus sign + *
, + * Number + * Yes + * Grouping separator + *
E + * Number + * Yes + * Separates mantissa and exponent in scientific notation. + * Need not be quoted in prefix or suffix. + *
; + * Subpattern boundary + * Yes + * Separates positive and negative subpatterns + *
% + * Prefix or suffix + * Yes + * Multiply by 100 and show as percentage + *
\u2030 + * Prefix or suffix + * Yes + * Multiply by 1000 and show as per mille value + *
¤ (\u00A4) + * Prefix or suffix + * No + * Currency sign, replaced by currency symbol. If doubled, replaced by + * international currency symbol. If present in a pattern, the monetary decimal + * separator is used instead of the decimal separator. + *
' + * Prefix or suffix + * No + * Used to quote special characters in a prefix or suffix, for example, + * "'#'#" formats 123 to "#123". To create a + * single quote itself, use two in a row: "# o''clock".
+ *
+ * + *

Scientific Notation

+ * + *

+ * Numbers in scientific notation are expressed as the product of a mantissa and + * a power of ten, for example, 1234 can be expressed as 1.234 x 10^3. The + * mantissa is often in the range 1.0 <= x < 10.0, but it need not be. + * DecimalFormat can be instructed to format and parse scientific + * notation only via a pattern; there is currently no factory method + * that creates a scientific notation format. In a pattern, the exponent + * character immediately followed by one or more digit characters indicates + * scientific notation. Example: "0.###E0" formats the number + * 1234 as "1.234E3". + * + *

    + *
  • The number of digit characters after the exponent character gives the + * minimum exponent digit count. There is no maximum. Negative exponents are + * formatted using the localized minus sign, not the prefix and + * suffix from the pattern. This allows patterns such as + * "0.###E0 m/s". + * + *
  • The minimum and maximum number of integer digits are interpreted + * together: + * + *
      + *
    • If the maximum number of integer digits is greater than their minimum + * number and greater than 1, it forces the exponent to be a multiple of the + * maximum number of integer digits, and the minimum number of integer digits to + * be interpreted as 1. The most common use of this is to generate + * engineering notation, in which the exponent is a multiple of + * three, e.g., "##0.#####E0". Using this pattern, the number + * 12345 formats to "12.345E3", and 123456 formats to + * "123.456E3". + * + *
    • Otherwise, the minimum number of integer digits is achieved by adjusting + * the exponent. Example: 0.00123 formatted with "00.###E0" + * yields "12.3E-4". + *
    + * + *
  • The number of significant digits in the mantissa is the sum of the + * minimum integer and maximum fraction digits, and is + * unaffected by the maximum integer digits. For example, 12345 formatted with + * "##0.##E0" is "12.3E3". To show all digits, + * set the significant digits count to zero. The number of significant digits + * does not affect parsing. + * + *
  • Exponential patterns may not contain grouping separators. + *
+ * + *

Rounding

+ * + * DecimalFormat uses half-even rounding (see + * {@link java.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for + * formatting. + * + *

Digits

+ * + * For formatting, DecimalFormat uses the ten consecutive + * characters starting with the localized zero digit defined in the + * DecimalFormatSymbols object as digits. For parsing, these + * digits as well as all Unicode decimal digits, as defined by + * {@link Character#digit Character.digit}, are recognized. + * + *

Special Values

+ * + *

+ * NaN is formatted as a single character, typically + * \uFFFD. This character is determined by the + * DecimalFormatSymbols object. This is the only value for which + * the prefixes and suffixes are not used. + * + *

+ * Infinity is formatted as a single character, typically + * \u221E, with the positive or negative prefixes and + * suffixes applied. The infinity character is determined by the + * DecimalFormatSymbols object. + * + *

+ * Negative zero ("-0") parses to + *

    + *
  • BigDecimal(0) if isParseBigDecimal() is + * true, + *
  • Long(0) if isParseBigDecimal() is false + * and isParseIntegerOnly() is true, + *
  • Double(-0.0) if both isParseBigDecimal() + * and isParseIntegerOnly() are false. + *
+ * + *

Synchronization

+ * + *

+ * Decimal formats are generally not synchronized. It is recommended to create + * separate format instances for each thread. If multiple threads access a + * format concurrently, it must be synchronized externally. + * + *

Example

+ * + *
+ * + *
+ * <strong>// Print out a number using the localized number, integer, currency,
+ * // and percent format for each locale</strong>
+ * Locale[] locales = NumberFormat.getAvailableLocales();
+ * double myNumber = -1234.56;
+ * NumberFormat form;
+ * for (int j=0; j<4; ++j) {
+ *     System.out.println("FORMAT");
+ *     for (int i = 0; i < locales.length; ++i) {
+ *         if (locales[i].getCountry().length() == 0) {
+ *            continue; // Skip language-only locales
+ *         }
+ *         System.out.print(locales[i].getDisplayName());
+ *         switch (j) {
+ *         case 0:
+ *             form = NumberFormat.getInstance(locales[i]); break;
+ *         case 1:
+ *             form = NumberFormat.getIntegerInstance(locales[i]); break;
+ *         case 2:
+ *             form = NumberFormat.getCurrencyInstance(locales[i]); break;
+ *         default:
+ *             form = NumberFormat.getPercentInstance(locales[i]); break;
+ *         }
+ *         if (form instanceof DecimalFormat) {
+ *             System.out.print(": " + ((DecimalFormat) form).toPattern());
+ *         }
+ *         System.out.print(" -> " + form.format(myNumber));
+ *         try {
+ *             System.out.println(" -> " + form.parse(form.format(myNumber)));
+ *         } catch (ParseException e) {}
+ *     }
+ * }
+ * 
+ * + *
+ * + * @see Java + * Tutorial + * @see NumberFormat + * @see DecimalFormatSymbols + * @see ParsePosition + * @version 1.79 06/28/04 + * @author Mark Davis + * @author Alan Liu + * @author Zachary O. Toups (toupsz@ecologylab.net) + */ +public class EfficientDecimalFormat extends DecimalFormat +{ + /** + * Creates a DecimalFormat using the given pattern and the symbols for the + * default locale. This is a convenient way to obtain a DecimalFormat when + * internationalization is not the main concern. + *

+ * To obtain standard formats for a given locale, use the factory methods on + * NumberFormat such as getNumberInstance. These factories will return the + * most appropriate sub-class of NumberFormat for a given locale. + * + * @param pattern + * A non-localized pattern string. + * @exception NullPointerException + * if pattern is null + * @exception IllegalArgumentException + * if the given pattern is invalid. + * @see java.text.NumberFormat#getInstance + * @see java.text.NumberFormat#getNumberInstance + * @see java.text.NumberFormat#getCurrencyInstance + * @see java.text.NumberFormat#getPercentInstance + */ + public EfficientDecimalFormat(String pattern) + { + // Always applyPattern after the symbols are set + this.symbols = new DecimalFormatSymbols(); + + applyPattern(pattern); + } + + /** + * Creates a DecimalFormat using the given pattern and symbols. Use this + * constructor when you need to completely customize the behavior of the + * format. + *

+ * To obtain standard formats for a given locale, use the factory methods on + * NumberFormat such as getInstance or getCurrencyInstance. If you need only + * minor adjustments to a standard format, you can modify the format returned + * by a NumberFormat factory method. + * + * @param pattern + * a non-localized pattern string + * @param symbols + * the set of symbols to be used + * @exception NullPointerException + * if any of the given arguments is null + * @exception IllegalArgumentException + * if the given pattern is invalid + * @see java.text.NumberFormat#getInstance + * @see java.text.NumberFormat#getNumberInstance + * @see java.text.NumberFormat#getCurrencyInstance + * @see java.text.NumberFormat#getPercentInstance + * @see java.text.DecimalFormatSymbols + */ + public EfficientDecimalFormat(String pattern, DecimalFormatSymbols symbols) + { + // Always applyPattern after the symbols are set + this.symbols = (DecimalFormatSymbols) symbols.clone(); + this.symbols.setNaN("NaN"); + + applyPattern(pattern); + } + + // Overrides + /** + * Formats a number and appends the resulting text to the given string + * buffer. The number can be of any subclass of {@link java.lang.Number}. + *

+ * This implementation uses the maximum precision permitted. + * + * @param number + * the number to format + * @param toAppendTo + * the StringBuffer to which the formatted text is + * to be appended + * @param pos + * On input: an alignment field, if desired. On output: the offsets + * of the alignment field. + * @return the value passed in as toAppendTo + * @throws IOException + * @exception IllegalArgumentException + * if number is null or not an instance of + * Number. + * @exception NullPointerException + * if toAppendTo or pos is null + * @see java.text.FieldPosition + */ + public final Appendable format(Object number, Appendable toAppendTo) + throws IOException + { + if (number instanceof Long + || number instanceof Integer + || number instanceof Short + || number instanceof Byte + || (number instanceof BigInteger && ((BigInteger) number) + .bitLength() < 64)) + { + return format(((Number) number).longValue(), toAppendTo); + } + else if (number instanceof BigDecimal) + { + return format((BigDecimal) number, toAppendTo); + } + else if (number instanceof BigInteger) + { + return format((BigInteger) number, toAppendTo); + } + else if (number instanceof Number) + { + return format(((Number) number).doubleValue(), toAppendTo); + } + else + { + throw new IllegalArgumentException( + "Cannot format given Object as a Number"); + } + } + + /** + * Formats a double to produce a string. + * + * @param number + * The double to format + * @param result + * where the text is to be appended + * @param delegate + * notified of locations of sub fields + * @return The formatted number string + * @throws IOException + */ + public Appendable format(double number, Appendable result) + throws IOException + { + if (Double.isNaN(number) + || (Double.isInfinite(number) && multiplier == 0)) + { + result.append(symbols.getNaN()); + + return result; + } + + /* + * Detecting whether a double is negative is easy with the exception of + * the value -0.0. This is a double which has a zero mantissa (and + * exponent), but a negative sign bit. It is semantically distinct from a + * zero with a positive sign bit, and this distinction is important to + * certain kinds of computations. However, it's a little tricky to detect, + * since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you may ask, does it + * behave distinctly from +0.0? Well, 1/(-0.0) == -Infinity. Proper + * detection of -0.0 is needed to deal with the issues raised by bugs + * 4106658, 4106667, and 4147706. Liu 7/6/98. + */ + boolean isNegative = ((number < 0.0) || (number == 0.0 && 1 / number < 0.0)) + ^ (multiplier < 0); + + if (multiplier != 1) + { + number *= multiplier; + } + + if (Double.isInfinite(number)) + { + if (isNegative) + { + result.append(negativePrefix); + } + else + { + result.append(positivePrefix); + } + + result.append(symbols.getInfinity()); + + if (isNegative) + { + result.append(negativeSuffix); + } + else + { + result.append(positiveSuffix); + } + + return result; + } + + if (isNegative) + { + number = -number; + } + + // at this point we are guaranteed a nonnegative finite number. + assert (number >= 0 && !Double.isInfinite(number)); + + synchronized (digitList) + { + int maxIntDigits = super.getMaximumIntegerDigits(); + int minIntDigits = super.getMinimumIntegerDigits(); + int maxFraDigits = super.getMaximumFractionDigits(); + int minFraDigits = super.getMinimumFractionDigits(); + + digitList.set(number, useExponentialNotation ? maxIntDigits + + maxFraDigits : maxFraDigits, !useExponentialNotation); + return subformat(result, isNegative, false, maxIntDigits, + minIntDigits, maxFraDigits, minFraDigits); + } + } + + /** + * Format a long to produce a string. + * + * @param number + * The long to format + * @param result + * where the text is to be appended + * @param delegate + * notified of locations of sub fields + * @return The formatted number string + * @throws IOException + * @see java.text.FieldPosition + */ + public Appendable format(long number, Appendable result) throws IOException + { + boolean isNegative = (number < 0); + if (isNegative) + { + number = -number; + } + + // In general, long values always represent real finite numbers, so + // we don't have to check for +/- Infinity or NaN. However, there + // is one case we have to be careful of: The multiplier can push + // a number near MIN_VALUE or MAX_VALUE outside the legal range. We + // check for this before multiplying, and if it happens we use + // BigInteger instead. + boolean useBigInteger = false; + if (number < 0) + { // This can only happen if number == Long.MIN_VALUE. + if (multiplier != 0) + { + useBigInteger = true; + } + } + else if (multiplier != 1 && multiplier != 0) + { + long cutoff = Long.MAX_VALUE / multiplier; + if (cutoff < 0) + { + cutoff = -cutoff; + } + useBigInteger = (number > cutoff); + } + + if (useBigInteger) + { + if (isNegative) + { + number = -number; + } + BigInteger bigIntegerValue = BigInteger.valueOf(number); + return format(bigIntegerValue, result, true); + } + + number *= multiplier; + if (number == 0) + { + isNegative = false; + } + else + { + if (multiplier < 0) + { + number = -number; + isNegative = !isNegative; + } + } + + synchronized (digitList) + { + int maxIntDigits = super.getMaximumIntegerDigits(); + int minIntDigits = super.getMinimumIntegerDigits(); + int maxFraDigits = super.getMaximumFractionDigits(); + int minFraDigits = super.getMinimumFractionDigits(); + + digitList.set(number, useExponentialNotation ? maxIntDigits + + maxFraDigits : 0); + + return subformat(result, isNegative, true, maxIntDigits, minIntDigits, + maxFraDigits, minFraDigits); + } + } + + /** + * Formats a BigDecimal to produce a string. + * + * @param number + * The BigDecimal to format + * @param result + * where the text is to be appended + * @param delegate + * notified of locations of sub fields + * @return The formatted number string + * @throws IOException + */ + public Appendable format(BigDecimal number, Appendable result) + throws IOException + { + if (multiplier != 1) + { + number = number.multiply(getBigDecimalMultiplier()); + } + boolean isNegative = number.signum() == -1; + if (isNegative) + { + number = number.negate(); + } + + synchronized (digitList) + { + int maxIntDigits = getMaximumIntegerDigits(); + int minIntDigits = getMinimumIntegerDigits(); + int maxFraDigits = getMaximumFractionDigits(); + int minFraDigits = getMinimumFractionDigits(); + int maximumDigits = maxIntDigits + maxFraDigits; + + digitList + .set( + number, + useExponentialNotation ? ((maximumDigits < 0) ? Integer.MAX_VALUE + : maximumDigits) + : maxFraDigits, !useExponentialNotation); + + return subformat(result, isNegative, false, maxIntDigits, + minIntDigits, maxFraDigits, minFraDigits); + } + } + + /** + * Format a BigInteger to produce a string. + * + * @param number + * The BigInteger to format + * @param result + * where the text is to be appended + * @param fieldPosition + * On input: an alignment field, if desired. On output: the offsets + * of the alignment field. + * @return The formatted number string + * @throws IOException + * @see java.text.FieldPosition + */ + private Appendable format(BigInteger number, Appendable result) + throws IOException + { + return format(number, result, false); + } + + /** + * Format a BigInteger to produce a string. + * + * @param number + * The BigInteger to format + * @param result + * where the text is to be appended + * @param delegate + * notified of locations of sub fields + * @return The formatted number string + * @throws IOException + * @see java.text.FieldPosition + */ + private Appendable format(BigInteger number, Appendable result, + boolean formatLong) throws IOException + { + if (multiplier != 1) + { + number = number.multiply(getBigIntegerMultiplier()); + } + boolean isNegative = number.signum() == -1; + if (isNegative) + { + number = number.negate(); + } + + synchronized (digitList) + { + int maxIntDigits, minIntDigits, maxFraDigits, minFraDigits, maximumDigits; + if (formatLong) + { + maxIntDigits = super.getMaximumIntegerDigits(); + minIntDigits = super.getMinimumIntegerDigits(); + maxFraDigits = super.getMaximumFractionDigits(); + minFraDigits = super.getMinimumFractionDigits(); + maximumDigits = maxIntDigits + maxFraDigits; + } + else + { + maxIntDigits = getMaximumIntegerDigits(); + minIntDigits = getMinimumIntegerDigits(); + maxFraDigits = getMaximumFractionDigits(); + minFraDigits = getMinimumFractionDigits(); + maximumDigits = maxIntDigits + maxFraDigits; + if (maximumDigits < 0) + { + maximumDigits = Integer.MAX_VALUE; + } + } + + digitList.set(number, useExponentialNotation ? maximumDigits : 0); + + return subformat(result, isNegative, true, maxIntDigits, minIntDigits, + maxFraDigits, minFraDigits); + } + } + + /** + * Complete the formatting of a finite number. On entry, the digitList must + * be filled in with the correct digits. + * + * @throws IOException + */ + private Appendable subformat(Appendable result, boolean isNegative, + boolean isInteger, int maxIntDigits, int minIntDigits, + int maxFraDigits, int minFraDigits) throws IOException + { + char zero = symbols.getZeroDigit(); + int zeroDelta = zero - '0'; // '0' is the DigitList representation of + // zero + char grouping = symbols.getGroupingSeparator(); + char decimal = isCurrencyFormat ? symbols.getMonetaryDecimalSeparator() + : symbols.getDecimalSeparator(); + + /* + * Per bug 4147706, DecimalFormat must respect the sign of numbers which + * format as zero. This allows sensible computations and preserves + * relations such as signum(1/x) = signum(x), where x is +Infinity or + * -Infinity. Prior to this fix, we always formatted zero values as if + * they were positive. Liu 7/6/98. + */ + if (digitList.isZero()) + digitList.decimalAt = 0; // Normalize + + if (isNegative) + result.append(negativePrefix); + else + result.append(positivePrefix); + + if (useExponentialNotation) + { + int iFieldEnd = -1; + int fFieldStart = -1; + + // Minimum integer digits are handled in exponential format by + // adjusting the exponent. For example, 0.01234 with 3 minimum + // integer digits is "123.4E-4". + + // Maximum integer digits are interpreted as indicating the + // repeating range. This is useful for engineering notation, in + // which the exponent is restricted to a multiple of 3. For + // example, 0.01234 with 3 maximum integer digits is "12.34e-3". + // If maximum integer digits are > 1 and are larger than + // minimum integer digits, then minimum integer digits are + // ignored. + int exponent = digitList.decimalAt; + int repeat = maxIntDigits; + if (repeat > 1 && repeat > minIntDigits) + { + // A repeating range is defined; adjust to it as follows. + // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3; + // -3,-4,-5=>-6, etc. This takes into account that the + // exponent we have here is off by one from what we expect; + // it is for the format 0.MMMMMx10^n. + if (exponent >= 1) + { + exponent = ((exponent - 1) / repeat) * repeat; + } + else + { + // integer division rounds towards 0 + exponent = ((exponent - repeat) / repeat) * repeat; + } + minimumIntegerDigits = 1; + } + else + { + // No repeating range is defined; use minimum integer digits. + exponent -= minimumIntegerDigits; + } + + // We now output a minimum number of digits, and more if there + // are more digits, up to the maximum number of digits. We + // place the decimal point after the "integer" digits, which + // are the first (decimalAt - exponent) digits. + int minimumDigits = minIntDigits + minFraDigits; + if (minimumDigits < 0) + { // overflow? + minimumDigits = Integer.MAX_VALUE; + } + + // The number of integer digits is handled specially if the number + // is zero, since then there may be no digits. + int integerDigits = digitList.isZero() ? minimumIntegerDigits + : digitList.decimalAt - exponent; + if (minimumDigits < integerDigits) + { + minimumDigits = integerDigits; + } + int totalDigits = digitList.count; + if (minimumDigits > totalDigits) + { + totalDigits = minimumDigits; + } + boolean addedDecimalSeparator = false; + + for (int i = 0; i < totalDigits; ++i) + { + if (i == integerDigits) + { + result.append(decimal); + addedDecimalSeparator = true; + } + result + .append((i < digitList.count) ? (char) (digitList.digits[i] + zeroDelta) + : zero); + } + + if (decimalSeparatorAlwaysShown && totalDigits == integerDigits) + { + result.append(decimal); + addedDecimalSeparator = true; + } + + // The exponent is output using the pattern-specified minimum + // exponent digits. There is no maximum limit to the exponent + // digits, since truncating the exponent would result in an + // unacceptable inaccuracy. + + result.append(symbols.getExponentialSymbol()); + + // For zero values, we force the exponent to zero. We + // must do this here, and not earlier, because the value + // is used to determine integer digit count above. + if (digitList.isZero()) + { + exponent = 0; + } + + boolean negativeExponent = exponent < 0; + if (negativeExponent) + { + exponent = -exponent; + result.append(symbols.getMinusSign()); + } + digitList.set(exponent); + + for (int i = digitList.decimalAt; i < minExponentDigits; ++i) + { + result.append(zero); + } + for (int i = 0; i < digitList.decimalAt; ++i) + { + result + .append((i < digitList.count) ? (char) (digitList.digits[i] + zeroDelta) + : zero); + } + } + else + { + // Output the integer portion. Here 'count' is the total + // number of integer digits we will display, including both + // leading zeros required to satisfy getMinimumIntegerDigits, + // and actual digits present in the number. + int count = minIntDigits; + int digitIndex = 0; // Index into digitList.fDigits[] + if (digitList.decimalAt > 0 && count < digitList.decimalAt) + { + count = digitList.decimalAt; + } + + // Handle the case where getMaximumIntegerDigits() is smaller + // than the real number of integer digits. If this is so, we + // output the least significant max integer digits. For example, + // the value 1997 printed with 2 max integer digits is just "97". + if (count > maxIntDigits) + { + count = maxIntDigits; + digitIndex = digitList.decimalAt - count; + } + + // indicate whether or not any characters have been appended before the + // fraction part + boolean actuallyAppended = (count - 1 < 0); + for (int i = count - 1; i >= 0; --i) + { + if (i < digitList.decimalAt && digitIndex < digitList.count) + { + // Output a real digit + result + .append((char) (digitList.digits[digitIndex++] + zeroDelta)); + + } + else + { + // Output a leading zero + result.append(zero); + } + + // Output grouping separator if necessary. Don't output a + // grouping separator if i==0 though; that's at the end of + // the integer part. + if (isGroupingUsed() && i > 0 && (groupingSize != 0) + && (i % groupingSize == 0)) + { + result.append(grouping); + } + } + + // Determine whether or not there are any printable fractional + // digits. If we've used up the digits we know there aren't. + boolean fractionPresent = (minFraDigits > 0) + || (!isInteger && digitIndex < digitList.count); + + // If there is no fraction present, and we haven't printed any + // integer digits, then print a zero. Otherwise we won't print + // _any_ digits, and we won't be able to parse this string. + if (!fractionPresent && actuallyAppended) + { + result.append(zero); + } + + // Output the decimal separator if we always do so. + if (decimalSeparatorAlwaysShown || fractionPresent) + { + result.append(decimal); + } + + for (int i = 0; i < maxFraDigits; ++i) + { + // Here is where we escape from the loop. We escape if we've + // output the maximum fraction digits (specified in the for + // expression above). + // We also stop when we've output the minimum digits and either: + // we have an integer, so there is no fractional stuff to + // display, or we're out of significant digits. + if (i >= minFraDigits + && (isInteger || digitIndex >= digitList.count)) + { + break; + } + + // Output leading fractional zeros. These are zeros that come + // after the decimal but before any significant digits. These + // are only output if abs(number being formatted) < 1.0. + if (-1 - i > (digitList.decimalAt - 1)) + { + result.append(zero); + continue; + } + + // Output a digit, if we have any precision left, or a + // zero if we don't. We don't want to output noise digits. + if (!isInteger && digitIndex < digitList.count) + { + result + .append((char) (digitList.digits[digitIndex++] + zeroDelta)); + } + else + { + result.append(zero); + } + } + } + + if (isNegative) + result.append(negativeSuffix); + else + result.append(positiveSuffix); + + return result; + } + + /** + * Parses text from a string to produce a Number. + *

+ * The method attempts to parse text starting at the index given by + * pos. If parsing succeeds, then the index of + * pos is updated to the index after the last character used + * (parsing does not necessarily use all characters up to the end of the + * string), and the parsed number is returned. The updated pos + * can be used to indicate the starting point for the next call to this + * method. If an error occurs, then the index of pos is not + * changed, the error index of pos is set to the index of the + * character where the error occurred, and null is returned. + *

+ * The subclass returned depends on the value of {@link #isParseBigDecimal} + * as well as on the string being parsed. + *

    + *
  • If isParseBigDecimal() is false (the default), most + * integer values are returned as Long objects, no matter how + * they are written: "17" and "17.000" both + * parse to Long(17). Values that cannot fit into a + * Long are returned as Doubles. This includes + * values with a fractional part, infinite values, NaN, and + * the value -0.0. DecimalFormat does not decide + * whether to return a Double or a Long based + * on the presence of a decimal separator in the source string. Doing so + * would prevent integers that overflow the mantissa of a double, such as + * "-9,223,372,036,854,775,808.00", from being parsed + * accurately. + *

    + * Callers may use the Number methods doubleValue, + * longValue, etc., to obtain the type they want. + *

  • If isParseBigDecimal() is true, values are returned as + * BigDecimal objects. The values are the ones constructed by + * {@link java.math.BigDecimal#BigDecimal(String)} for corresponding strings + * in locale-independent format. The special cases negative and positive + * infinity and NaN are returned as Double instances holding + * the values of the corresponding Double constants. + *
+ *

+ * DecimalFormat parses all Unicode characters that represent + * decimal digits, as defined by Character.digit(). In + * addition, DecimalFormat also recognizes as digits the ten + * consecutive characters starting with the localized zero digit defined in + * the DecimalFormatSymbols object. + * + * @param text + * the string to be parsed + * @param pos + * A ParsePosition object with index and error index + * information as described above. + * @return the parsed value, or null if the parse fails + * @exception NullPointerException + * if text or pos is null. + */ + @Override + public Number parse(String text, ParsePosition pos) + { + // special case NaN + if (text.regionMatches(pos.getIndex(), symbols.getNaN(), 0, symbols + .getNaN().length())) + { + pos.setIndex(pos.getIndex() + symbols.getNaN().length()); + return new Double(Double.NaN); + } + + boolean[] status = new boolean[STATUS_LENGTH]; + if (!subparse(text, pos, positivePrefix, negativePrefix, digitList, + false, status)) + { + return null; + } + + // special case INFINITY + if (status[STATUS_INFINITE]) + { + if (status[STATUS_POSITIVE] == (multiplier >= 0)) + { + return new Double(Double.POSITIVE_INFINITY); + } + else + { + return new Double(Double.NEGATIVE_INFINITY); + } + } + + if (multiplier == 0) + { + if (digitList.isZero()) + { + return new Double(Double.NaN); + } + else if (status[STATUS_POSITIVE]) + { + return new Double(Double.POSITIVE_INFINITY); + } + else + { + return new Double(Double.NEGATIVE_INFINITY); + } + } + + if (isParseBigDecimal()) + { + BigDecimal bigDecimalResult = digitList.getBigDecimal(); + + if (multiplier != 1) + { + try + { + bigDecimalResult = bigDecimalResult + .divide(getBigDecimalMultiplier()); + } + catch (ArithmeticException e) + { // non-terminating decimal expansion + bigDecimalResult = bigDecimalResult.divide( + getBigDecimalMultiplier(), BigDecimal.ROUND_HALF_EVEN); + } + } + + if (!status[STATUS_POSITIVE]) + { + bigDecimalResult = bigDecimalResult.negate(); + } + return bigDecimalResult; + } + else + { + boolean gotDouble = true; + boolean gotLongMinimum = false; + double doubleResult = 0.0; + long longResult = 0; + + // Finally, have DigitList parse the digits into a value. + if (digitList.fitsIntoLong(status[STATUS_POSITIVE], + isParseIntegerOnly())) + { + gotDouble = false; + longResult = digitList.getLong(); + if (longResult < 0) + { // got Long.MIN_VALUE + gotLongMinimum = true; + } + } + else + { + doubleResult = digitList.getDouble(); + } + + // Divide by multiplier. We have to be careful here not to do + // unneeded conversions between double and long. + if (multiplier != 1) + { + if (gotDouble) + { + doubleResult /= multiplier; + } + else + { + // Avoid converting to double if we can + if (longResult % multiplier == 0) + { + longResult /= multiplier; + } + else + { + doubleResult = ((double) longResult) / multiplier; + gotDouble = true; + } + } + } + + if (!status[STATUS_POSITIVE] && !gotLongMinimum) + { + doubleResult = -doubleResult; + longResult = -longResult; + } + + // At this point, if we divided the result by the multiplier, the + // result may fit into a long. We check for this case and return + // a long if possible. + // We must do this AFTER applying the negative (if appropriate) + // in order to handle the case of LONG_MIN; otherwise, if we do + // this with a positive value -LONG_MIN, the double is > 0, but + // the long is < 0. We also must retain a double in the case of + // -0.0, which will compare as == to a long 0 cast to a double + // (bug 4162852). + if (multiplier != 1 && gotDouble) + { + longResult = (long) doubleResult; + gotDouble = ((doubleResult != longResult) || (doubleResult == 0.0 && 1 / doubleResult < 0.0)) + && !isParseIntegerOnly(); + } + + return gotDouble ? (Number) new Double(doubleResult) + : (Number) new Long(longResult); + } + } + + /** + * Return a BigInteger multiplier. + */ + private BigInteger getBigIntegerMultiplier() + { + if (bigIntegerMultiplier == null) + { + bigIntegerMultiplier = BigInteger.valueOf(multiplier); + } + return bigIntegerMultiplier; + } + + private transient BigInteger bigIntegerMultiplier; + + /** + * Return a BigDecimal multiplier. + */ + private BigDecimal getBigDecimalMultiplier() + { + if (bigDecimalMultiplier == null) + { + bigDecimalMultiplier = new BigDecimal(multiplier); + } + return bigDecimalMultiplier; + } + + private transient BigDecimal bigDecimalMultiplier; + + private static final int STATUS_INFINITE = 0; + + private static final int STATUS_POSITIVE = 1; + + private static final int STATUS_LENGTH = 2; + + /** + * Parse the given text into a number. The text is parsed beginning at + * parsePosition, until an unparseable character is seen. + * + * @param text + * The string to parse. + * @param parsePosition + * The position at which to being parsing. Upon return, the first + * unparseable character. + * @param digits + * The DigitList to set to the parsed value. + * @param isExponent + * If true, parse an exponent. This means no infinite values and + * integer only. + * @param status + * Upon return contains boolean status flags indicating whether the + * value was infinite and whether it was positive. + */ + private final boolean subparse(String text, ParsePosition parsePosition, + String positivePrefix, String negativePrefix, DigitList digits, + boolean isExponent, boolean status[]) + { + int position = parsePosition.getIndex(); + int oldStart = parsePosition.getIndex(); + int backup; + boolean gotPositive, gotNegative; + + // check for positivePrefix; take longest + gotPositive = text.regionMatches(position, positivePrefix, 0, + positivePrefix.length()); + gotNegative = text.regionMatches(position, negativePrefix, 0, + negativePrefix.length()); + + if (gotPositive && gotNegative) + { + if (positivePrefix.length() > negativePrefix.length()) + { + gotNegative = false; + } + else if (positivePrefix.length() < negativePrefix.length()) + { + gotPositive = false; + } + } + + if (gotPositive) + { + position += positivePrefix.length(); + } + else if (gotNegative) + { + position += negativePrefix.length(); + } + else + { + parsePosition.setErrorIndex(position); + return false; + } + + // process digits or Inf, find decimal position + status[STATUS_INFINITE] = false; + if (!isExponent + && text.regionMatches(position, symbols.getInfinity(), 0, symbols + .getInfinity().length())) + { + position += symbols.getInfinity().length(); + status[STATUS_INFINITE] = true; + } + else + { + // We now have a string of digits, possibly with grouping symbols, + // and decimal points. We want to process these into a DigitList. + // We don't want to put a bunch of leading zeros into the DigitList + // though, so we keep track of the location of the decimal point, + // put only significant digits into the DigitList, and adjust the + // exponent as needed. + + digits.decimalAt = digits.count = 0; + char zero = symbols.getZeroDigit(); + char decimal = isCurrencyFormat ? symbols + .getMonetaryDecimalSeparator() : symbols.getDecimalSeparator(); + char grouping = symbols.getGroupingSeparator(); + char exponentChar = symbols.getExponentialSymbol(); + boolean sawDecimal = false; + boolean sawExponent = false; + boolean sawDigit = false; + int exponent = 0; // Set to the exponent value, if any + + // We have to track digitCount ourselves, because digits.count will + // pin when the maximum allowable digits is reached. + int digitCount = 0; + + backup = -1; + for (; position < text.length(); ++position) + { + char ch = text.charAt(position); + + /* + * We recognize all digit ranges, not only the Latin digit range + * '0'..'9'. We do so by using the Character.digit() method, which + * converts a valid Unicode digit to the range 0..9. + * + * The character 'ch' may be a digit. If so, place its value from 0 + * to 9 in 'digit'. First try using the locale digit, which may or + * MAY NOT be a standard Unicode digit range. If this fails, try + * using the standard Unicode digit ranges by calling + * Character.digit(). If this also fails, digit will have a value + * outside the range 0..9. + */ + int digit = ch - zero; + if (digit < 0 || digit > 9) + { + digit = Character.digit(ch, 10); + } + + if (digit == 0) + { + // Cancel out backup setting (see grouping handler below) + backup = -1; // Do this BEFORE continue statement below!!! + sawDigit = true; + + // Handle leading zeros + if (digits.count == 0) + { + // Ignore leading zeros in integer part of number. + if (!sawDecimal) + { + continue; + } + + // If we have seen the decimal, but no significant + // digits yet, then we account for leading zeros by + // decrementing the digits.decimalAt into negative + // values. + --digits.decimalAt; + } + else + { + ++digitCount; + digits.append((char) (digit + '0')); + } + } + else if (digit > 0 && digit <= 9) + { // [sic] digit==0 handled above + sawDigit = true; + ++digitCount; + digits.append((char) (digit + '0')); + + // Cancel out backup setting (see grouping handler below) + backup = -1; + } + else if (!isExponent && ch == decimal) + { + // If we're only parsing integers, or if we ALREADY saw the + // decimal, then don't parse this one. + if (isParseIntegerOnly() || sawDecimal) + { + break; + } + digits.decimalAt = digitCount; // Not digits.count! + sawDecimal = true; + } + else if (!isExponent && ch == grouping && isGroupingUsed()) + { + if (sawDecimal) + { + break; + } + // Ignore grouping characters, if we are using them, but + // require that they be followed by a digit. Otherwise + // we backup and reprocess them. + backup = position; + } + else if (!isExponent && ch == exponentChar && !sawExponent) + { + // Process the exponent by recursively calling this method. + ParsePosition pos = new ParsePosition(position + 1); + boolean[] stat = new boolean[STATUS_LENGTH]; + DigitList exponentDigits = new DigitList(); + + if (subparse(text, pos, "", Character.toString(symbols + .getMinusSign()), exponentDigits, true, stat) + && exponentDigits + .fitsIntoLong(stat[STATUS_POSITIVE], true)) + { + position = pos.getIndex(); // Advance past the exponent + exponent = (int) exponentDigits.getLong(); + if (!stat[STATUS_POSITIVE]) + { + exponent = -exponent; + } + sawExponent = true; + } + break; // Whether we fail or succeed, we exit this loop + } + else + { + break; + } + } + + if (backup != -1) + { + position = backup; + } + + // If there was no decimal point we have an integer + if (!sawDecimal) + { + digits.decimalAt = digitCount; // Not digits.count! + } + + // Adjust for exponent, if any + digits.decimalAt += exponent; + + // If none of the text string was recognized. For example, parse + // "x" with pattern "#0.00" (return index and error index both 0) + // parse "$" with pattern "$#0.00". (return index 0 and error + // index 1). + if (!sawDigit && digitCount == 0) + { + parsePosition.setIndex(oldStart); + parsePosition.setErrorIndex(oldStart); + return false; + } + } + + // check for suffix + if (!isExponent) + { + if (gotPositive) + { + gotPositive = text.regionMatches(position, positiveSuffix, 0, + positiveSuffix.length()); + } + if (gotNegative) + { + gotNegative = text.regionMatches(position, negativeSuffix, 0, + negativeSuffix.length()); + } + + // if both match, take longest + if (gotPositive && gotNegative) + { + if (positiveSuffix.length() > negativeSuffix.length()) + { + gotNegative = false; + } + else if (positiveSuffix.length() < negativeSuffix.length()) + { + gotPositive = false; + } + } + + // fail if neither or both + if (gotPositive == gotNegative) + { + parsePosition.setErrorIndex(position); + return false; + } + + parsePosition.setIndex(position + + (gotPositive ? positiveSuffix.length() : negativeSuffix + .length())); // mark success! + } + else + { + parsePosition.setIndex(position); + } + + status[STATUS_POSITIVE] = gotPositive; + if (parsePosition.getIndex() == oldStart) + { + parsePosition.setErrorIndex(position); + return false; + } + return true; + } + + /** + * Sets the decimal format symbols, which is generally not changed by the + * programmer or user. + * + * @param newSymbols + * desired DecimalFormatSymbols + * @see java.text.DecimalFormatSymbols + */ + public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) + { + try + { + // don't allow multiple references + symbols = (DecimalFormatSymbols) newSymbols.clone(); + expandAffixes(); + } + catch (Exception foo) + { + // should never happen + } + } + + /** + * Get the positive prefix. + *

+ * Examples: +123, $123, sFr123 + */ + @Override public String getPositivePrefix() + { + return positivePrefix; + } + + /** + * Set the positive prefix. + *

+ * Examples: +123, $123, sFr123 + */ + @Override public void setPositivePrefix(String newValue) + { + positivePrefix = newValue; + posPrefixPattern = null; + positivePrefixFieldPositions = null; + } + + /** + * Get the negative prefix. + *

+ * Examples: -123, ($123) (with negative suffix), sFr-123 + */ + @Override public String getNegativePrefix() + { + return negativePrefix; + } + + /** + * Set the negative prefix. + *

+ * Examples: -123, ($123) (with negative suffix), sFr-123 + */ + @Override public void setNegativePrefix(String newValue) + { + negativePrefix = newValue; + negPrefixPattern = null; + } + + /** + * Get the positive suffix. + *

+ * Example: 123% + */ + @Override public String getPositiveSuffix() + { + return positiveSuffix; + } + + /** + * Set the positive suffix. + *

+ * Example: 123% + */ + @Override public void setPositiveSuffix(String newValue) + { + positiveSuffix = newValue; + posSuffixPattern = null; + } + + /** + * Get the negative suffix. + *

+ * Examples: -123%, ($123) (with positive suffixes) + */ + @Override public String getNegativeSuffix() + { + return negativeSuffix; + } + + /** + * Set the negative suffix. + *

+ * Examples: 123% + */ + @Override public void setNegativeSuffix(String newValue) + { + negativeSuffix = newValue; + negSuffixPattern = null; + } + + /** + * Gets the multiplier for use in percent, per mille, and similar formats. + * + * @see #setMultiplier(int) + */ + @Override public int getMultiplier() + { + return multiplier; + } + + /** + * Sets the multiplier for use in percent, per mille, and similar formats. + * For a percent format, set the multiplier to 100 and the suffixes to have + * '%' (for Arabic, use the Arabic percent sign). For a per mille format, set + * the multiplier to 1000 and the suffixes to have '\u2030'. + * + *

+ * Example: with multiplier 100, 1.23 is formatted as "123", and "123" is + * parsed into 1.23. + * + * @see #getMultiplier + */ + @Override public void setMultiplier(int newValue) + { + multiplier = newValue; + bigDecimalMultiplier = null; + bigIntegerMultiplier = null; + } + + /** + * Return the grouping size. Grouping size is the number of digits between + * grouping separators in the integer portion of a number. For example, in + * the number "123,456.78", the grouping size is 3. + * + * @see #setGroupingSize + * @see java.text.NumberFormat#isGroupingUsed + * @see java.text.DecimalFormatSymbols#getGroupingSeparator + */ + @Override public int getGroupingSize() + { + return groupingSize; + } + + /** + * Set the grouping size. Grouping size is the number of digits between + * grouping separators in the integer portion of a number. For example, in + * the number "123,456.78", the grouping size is 3.
+ * The value passed in is converted to a byte, which may lose information. + * + * @see #getGroupingSize + * @see java.text.NumberFormat#setGroupingUsed + * @see java.text.DecimalFormatSymbols#setGroupingSeparator + */ + @Override public void setGroupingSize(int newValue) + { + groupingSize = (byte) newValue; + } + + /** + * Allows you to get the behavior of the decimal separator with integers. + * (The decimal separator will always appear with decimals.) + *

+ * Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345 + */ + @Override public boolean isDecimalSeparatorAlwaysShown() + { + return decimalSeparatorAlwaysShown; + } + + /** + * Allows you to set the behavior of the decimal separator with integers. + * (The decimal separator will always appear with decimals.) + *

+ * Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345 + */ + @Override public void setDecimalSeparatorAlwaysShown(boolean newValue) + { + decimalSeparatorAlwaysShown = newValue; + } + + /** + * Returns whether the + * {@link #parse(java.lang.String, java.text.ParsePosition)} method returns + * BigDecimal. The default value is false. + * + * @see #setParseBigDecimal + * @since 1.5 + */ + @Override public boolean isParseBigDecimal() + { + return parseBigDecimal; + } + + /** + * Sets whether the {@link #parse(java.lang.String, java.text.ParsePosition)} + * method returns BigDecimal. + * + * @see #isParseBigDecimal + * @since 1.5 + */ + @Override public void setParseBigDecimal(boolean newValue) + { + parseBigDecimal = newValue; + } + + /** + * Standard override; no change in semantics. + */ + @Override public Object clone() + { + try + { + EfficientDecimalFormat other = (EfficientDecimalFormat) super.clone(); + other.symbols = (DecimalFormatSymbols) symbols.clone(); + other.digitList = (DigitList) digitList.clone(); + return other; + } + catch (Exception e) + { + throw new InternalError(); + } + } + + /** + * Overrides equals + */ + @Override public boolean equals(Object obj) + { + if (obj == null) + return false; + if (!super.equals(obj)) + return false; // super does class check + EfficientDecimalFormat other = (EfficientDecimalFormat) obj; + return ((posPrefixPattern == other.posPrefixPattern && positivePrefix + .equals(other.positivePrefix)) || (posPrefixPattern != null && posPrefixPattern + .equals(other.posPrefixPattern))) + && ((posSuffixPattern == other.posSuffixPattern && positiveSuffix + .equals(other.positiveSuffix)) || (posSuffixPattern != null && posSuffixPattern + .equals(other.posSuffixPattern))) + && ((negPrefixPattern == other.negPrefixPattern && negativePrefix + .equals(other.negativePrefix)) || (negPrefixPattern != null && negPrefixPattern + .equals(other.negPrefixPattern))) + && ((negSuffixPattern == other.negSuffixPattern && negativeSuffix + .equals(other.negativeSuffix)) || (negSuffixPattern != null && negSuffixPattern + .equals(other.negSuffixPattern))) + && multiplier == other.multiplier + && groupingSize == other.groupingSize + && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown + && parseBigDecimal == other.parseBigDecimal + && useExponentialNotation == other.useExponentialNotation + && (!useExponentialNotation || minExponentDigits == other.minExponentDigits) + && maximumIntegerDigits == other.maximumIntegerDigits + && minimumIntegerDigits == other.minimumIntegerDigits + && maximumFractionDigits == other.maximumFractionDigits + && minimumFractionDigits == other.minimumFractionDigits + && symbols.equals(other.symbols); + } + + /** + * Overrides hashCode + */ + @Override public int hashCode() + { + return super.hashCode() * 37 + positivePrefix.hashCode(); + // just enough fields for a reasonable distribution + } + + /** + * Synthesizes a pattern string that represents the current state of this + * Format object. + * + * @see #applyPattern + */ + @Override public String toPattern() + { + return toPattern(false); + } + + /** + * Synthesizes a localized pattern string that represents the current state + * of this Format object. + * + * @see #applyPattern + */ + @Override public String toLocalizedPattern() + { + return toPattern(true); + } + + /** + * Expand the affix pattern strings into the expanded affix strings. If any + * affix pattern string is null, do not expand it. This method should be + * called any time the symbols or the affix patterns change in order to keep + * the expanded affix strings up to date. + */ + private void expandAffixes() + { + // Reuse one StringBuffer for better performance + StringBuffer buffer = new StringBuffer(); + if (posPrefixPattern != null) + { + positivePrefix = expandAffix(posPrefixPattern, buffer); + positivePrefixFieldPositions = null; + } + if (posSuffixPattern != null) + { + positiveSuffix = expandAffix(posSuffixPattern, buffer); + positiveSuffixFieldPositions = null; + } + if (negPrefixPattern != null) + { + negativePrefix = expandAffix(negPrefixPattern, buffer); + negativePrefixFieldPositions = null; + } + if (negSuffixPattern != null) + { + negativeSuffix = expandAffix(negSuffixPattern, buffer); + negativeSuffixFieldPositions = null; + } + } + + /** + * Expand an affix pattern into an affix string. All characters in the + * pattern are literal unless prefixed by QUOTE. The following characters + * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, + * PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE + + * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217 currency + * code. Any other character after a QUOTE represents itself. QUOTE must be + * followed by another character; QUOTE may not occur by itself at the end of + * the pattern. + * + * @param pattern + * the non-null, possibly empty pattern + * @param buffer + * a scratch StringBuffer; its contents will be lost + * @return the expanded equivalent of pattern + */ + private String expandAffix(String pattern, StringBuffer buffer) + { + buffer.setLength(0); + for (int i = 0; i < pattern.length();) + { + char c = pattern.charAt(i++); + if (c == QUOTE) + { + c = pattern.charAt(i++); + switch (c) + { + case CURRENCY_SIGN: + if (i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN) + { + ++i; + buffer.append(symbols.getInternationalCurrencySymbol()); + } + else + { + buffer.append(symbols.getCurrencySymbol()); + } + continue; + case PATTERN_PERCENT: + c = symbols.getPercent(); + break; + case PATTERN_PER_MILLE: + c = symbols.getPerMill(); + break; + case PATTERN_MINUS: + c = symbols.getMinusSign(); + break; + } + } + buffer.append(c); + } + return buffer.toString(); + } + + /** + * Appends an affix pattern to the given StringBuffer, quoting special + * characters as needed. Uses the internal affix pattern, if that exists, or + * the literal affix, if the internal affix pattern is null. The appended + * string will generate the same affix pattern (or literal affix) when passed + * to toPattern(). + * + * @param buffer + * the affix string is appended to this + * @param affixPattern + * a pattern such as posPrefixPattern; may be null + * @param expAffix + * a corresponding expanded affix, such as positivePrefix. Ignored + * unless affixPattern is null. If affixPattern is null, then + * expAffix is appended as a literal affix. + * @param localized + * true if the appended pattern should contain localized pattern + * characters; otherwise, non-localized pattern chars are appended + */ + private void appendAffix(StringBuffer buffer, String affixPattern, + String expAffix, boolean localized) + { + if (affixPattern == null) + { + appendAffix(buffer, expAffix, localized); + } + else + { + int i; + for (int pos = 0; pos < affixPattern.length(); pos = i) + { + i = affixPattern.indexOf(QUOTE, pos); + if (i < 0) + { + appendAffix(buffer, affixPattern.substring(pos), localized); + break; + } + if (i > pos) + { + appendAffix(buffer, affixPattern.substring(pos, i), localized); + } + char c = affixPattern.charAt(++i); + ++i; + if (c == QUOTE) + { + buffer.append(c); + // Fall through and append another QUOTE below + } + else if (c == CURRENCY_SIGN && i < affixPattern.length() + && affixPattern.charAt(i) == CURRENCY_SIGN) + { + ++i; + buffer.append(c); + // Fall through and append another CURRENCY_SIGN below + } + else if (localized) + { + switch (c) + { + case PATTERN_PERCENT: + c = symbols.getPercent(); + break; + case PATTERN_PER_MILLE: + c = symbols.getPerMill(); + break; + case PATTERN_MINUS: + c = symbols.getMinusSign(); + break; + } + } + buffer.append(c); + } + } + } + + /** + * Append an affix to the given StringBuffer, using quotes if there are + * special characters. Single quotes themselves must be escaped in either + * case. + */ + private void appendAffix(StringBuffer buffer, String affix, boolean localized) + { + boolean needQuote; + if (localized) + { + needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0 + || affix.indexOf(symbols.getGroupingSeparator()) >= 0 + || affix.indexOf(symbols.getDecimalSeparator()) >= 0 + || affix.indexOf(symbols.getPercent()) >= 0 + || affix.indexOf(symbols.getPerMill()) >= 0 + || affix.indexOf(symbols.getDigit()) >= 0 + || affix.indexOf(symbols.getPatternSeparator()) >= 0 + || affix.indexOf(symbols.getMinusSign()) >= 0 + || affix.indexOf(CURRENCY_SIGN) >= 0; + } + else + { + needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0 + || affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 0 + || affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 0 + || affix.indexOf(PATTERN_PERCENT) >= 0 + || affix.indexOf(PATTERN_PER_MILLE) >= 0 + || affix.indexOf(PATTERN_DIGIT) >= 0 + || affix.indexOf(PATTERN_SEPARATOR) >= 0 + || affix.indexOf(PATTERN_MINUS) >= 0 + || affix.indexOf(CURRENCY_SIGN) >= 0; + } + if (needQuote) + buffer.append('\''); + if (affix.indexOf('\'') < 0) + buffer.append(affix); + else + { + for (int j = 0; j < affix.length(); ++j) + { + char c = affix.charAt(j); + buffer.append(c); + if (c == '\'') + buffer.append(c); + } + } + if (needQuote) + buffer.append('\''); + } + + /** + * Does the real work of generating a pattern. + */ + private String toPattern(boolean localized) + { + StringBuffer result = new StringBuffer(); + for (int j = 1; j >= 0; --j) + { + if (j == 1) + appendAffix(result, posPrefixPattern, positivePrefix, localized); + else + appendAffix(result, negPrefixPattern, negativePrefix, localized); + int i; + int digitCount = useExponentialNotation ? getMaximumIntegerDigits() + : Math.max(groupingSize, getMinimumIntegerDigits()) + 1; + for (i = digitCount; i > 0; --i) + { + if (i != digitCount && isGroupingUsed() && groupingSize != 0 + && i % groupingSize == 0) + { + result.append(localized ? symbols.getGroupingSeparator() + : PATTERN_GROUPING_SEPARATOR); + } + result.append(i <= getMinimumIntegerDigits() ? (localized ? symbols + .getZeroDigit() : PATTERN_ZERO_DIGIT) : (localized ? symbols + .getDigit() : PATTERN_DIGIT)); + } + if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) + result.append(localized ? symbols.getDecimalSeparator() + : PATTERN_DECIMAL_SEPARATOR); + for (i = 0; i < getMaximumFractionDigits(); ++i) + { + if (i < getMinimumFractionDigits()) + { + result.append(localized ? symbols.getZeroDigit() + : PATTERN_ZERO_DIGIT); + } + else + { + result.append(localized ? symbols.getDigit() : PATTERN_DIGIT); + } + } + if (useExponentialNotation) + { + result.append(localized ? symbols.getExponentialSymbol() + : PATTERN_EXPONENT); + for (i = 0; i < minExponentDigits; ++i) + result.append(localized ? symbols.getZeroDigit() + : PATTERN_ZERO_DIGIT); + } + if (j == 1) + { + appendAffix(result, posSuffixPattern, positiveSuffix, localized); + if ((negSuffixPattern == posSuffixPattern && // n == p == null + negativeSuffix.equals(positiveSuffix)) + || (negSuffixPattern != null && negSuffixPattern + .equals(posSuffixPattern))) + { + if ((negPrefixPattern != null && posPrefixPattern != null && negPrefixPattern + .equals("'-" + posPrefixPattern)) + || (negPrefixPattern == posPrefixPattern && // n == p == + // null + negativePrefix.equals(symbols.getMinusSign() + + positivePrefix))) + break; + } + result.append(localized ? symbols.getPatternSeparator() + : PATTERN_SEPARATOR); + } + else + appendAffix(result, negSuffixPattern, negativeSuffix, localized); + } + return result.toString(); + } + + /** + * Apply the given pattern to this Format object. The pattern is assumed to + * be in a localized notation. A pattern is a short-hand specification for + * the various formatting properties. These properties can also be changed + * individually through the various setter methods. + *

+ * There is no limit to integer digits are set by this routine, since that is + * the typical end-user desire; use setMaximumInteger if you want to set a + * real value. For negative numbers, use a second pattern, separated by a + * semicolon + *

+ * Example "#,#00.0#" -> 1,234.56 + *

+ * This means a minimum of 2 integer digits, 1 fraction digit, and a maximum + * of 2 fraction digits. + *

+ * Example: "#,#00.0#;(#,#00.0#)" for negatives in + * parentheses. + *

+ * In negative patterns, the minimum and maximum counts are ignored; these + * are presumed to be set in the positive pattern. + * + * @exception NullPointerException + * if pattern is null + * @exception IllegalArgumentException + * if the given pattern is invalid. + */ + @Override public void applyLocalizedPattern(String pattern) + { + applyPattern(pattern); + } + + /** + * Does the real work of applying a pattern. + */ + @Override public void applyPattern(String pattern) + { + char zeroDigit = PATTERN_ZERO_DIGIT; + char groupingSeparator = PATTERN_GROUPING_SEPARATOR; + char decimalSeparator = PATTERN_DECIMAL_SEPARATOR; + char percent = PATTERN_PERCENT; + char perMill = PATTERN_PER_MILLE; + char digit = PATTERN_DIGIT; + char separator = PATTERN_SEPARATOR; + char exponent = PATTERN_EXPONENT; + char minus = PATTERN_MINUS; + + zeroDigit = symbols.getZeroDigit(); + groupingSeparator = symbols.getGroupingSeparator(); + decimalSeparator = symbols.getDecimalSeparator(); + percent = symbols.getPercent(); + perMill = symbols.getPerMill(); + digit = symbols.getDigit(); + separator = symbols.getPatternSeparator(); + exponent = symbols.getExponentialSymbol(); + minus = symbols.getMinusSign(); + + boolean gotNegative = false; + decimalSeparatorAlwaysShown = false; + isCurrencyFormat = false; + useExponentialNotation = false; + + // Two variables are used to record the subrange of the pattern + // occupied by phase 1. This is used during the processing of the + // second pattern (the one representing negative numbers) to ensure + // that no deviation exists in phase 1 between the two patterns. + int phaseOneStart = 0; + int phaseOneLength = 0; + + int start = 0; + for (int j = 1; j >= 0 && start < pattern.length(); --j) + { + boolean inQuote = false; + StringBuffer prefix = new StringBuffer(); + StringBuffer suffix = new StringBuffer(); + int decimalPos = -1; + int multiplier = 1; + int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0; + byte groupingCount = -1; + + // The phase ranges from 0 to 2. Phase 0 is the prefix. Phase 1 is + // the section of the pattern with digits, decimal separator, + // grouping characters. Phase 2 is the suffix. In phases 0 and 2, + // percent, per mille, and currency symbols are recognized and + // translated. The separation of the characters into phases is + // strictly enforced; if phase 1 characters are to appear in the + // suffix, for example, they must be quoted. + int phase = 0; + + // The affix is either the prefix or the suffix. + StringBuffer affix = prefix; + + for (int pos = start; pos < pattern.length(); ++pos) + { + char ch = pattern.charAt(pos); + switch (phase) + { + case 0: + case 2: + // Process the prefix / suffix characters + if (inQuote) + { + // A quote within quotes indicates either the closing + // quote or two quotes, which is a quote literal. That + // is, we have the second quote in 'do' or 'don''t'. + if (ch == QUOTE) + { + if ((pos + 1) < pattern.length() + && pattern.charAt(pos + 1) == QUOTE) + { + ++pos; + affix.append("''"); // 'don''t' + } + else + { + inQuote = false; // 'do' + } + continue; + } + } + else + { + // Process unquoted characters seen in prefix or suffix + // phase. + if (ch == digit || ch == zeroDigit || ch == groupingSeparator + || ch == decimalSeparator) + { + phase = 1; + if (j == 1) + { + phaseOneStart = pos; + } + --pos; // Reprocess this character + continue; + } + else if (ch == CURRENCY_SIGN) + { + // Use lookahead to determine if the currency sign + // is doubled or not. + boolean doubled = (pos + 1) < pattern.length() + && pattern.charAt(pos + 1) == CURRENCY_SIGN; + if (doubled) + { // Skip over the doubled character + ++pos; + } + isCurrencyFormat = true; + affix.append(doubled ? "'\u00A4\u00A4" : "'\u00A4"); + continue; + } + else if (ch == QUOTE) + { + // A quote outside quotes indicates either the + // opening quote or two quotes, which is a quote + // literal. That is, we have the first quote in 'do' + // or o''clock. + if (ch == QUOTE) + { + if ((pos + 1) < pattern.length() + && pattern.charAt(pos + 1) == QUOTE) + { + ++pos; + affix.append("''"); // o''clock + } + else + { + inQuote = true; // 'do' + } + continue; + } + } + else if (ch == separator) + { + // Don't allow separators before we see digit + // characters of phase 1, and don't allow separators + // in the second pattern (j == 0). + if (phase == 0 || j == 0) + { + throw new IllegalArgumentException( + "Unquoted special character '" + ch + + "' in pattern \"" + pattern + '"'); + } + start = pos + 1; + pos = pattern.length(); + continue; + } + + // Next handle characters which are appended directly. + else if (ch == percent) + { + if (multiplier != 1) + { + throw new IllegalArgumentException( + "Too many percent/per mille characters in pattern \"" + + pattern + '"'); + } + multiplier = 100; + affix.append("'%"); + continue; + } + else if (ch == perMill) + { + if (multiplier != 1) + { + throw new IllegalArgumentException( + "Too many percent/per mille characters in pattern \"" + + pattern + '"'); + } + multiplier = 1000; + affix.append("'\u2030"); + continue; + } + else if (ch == minus) + { + affix.append("'-"); + continue; + } + } + // Note that if we are within quotes, or if this is an + // unquoted, non-special character, then we usually fall + // through to here. + affix.append(ch); + break; + + case 1: + // Phase one must be identical in the two sub-patterns. We + // enforce this by doing a direct comparison. While + // processing the first sub-pattern, we just record its + // length. While processing the second, we compare + // characters. + if (j == 1) + { + ++phaseOneLength; + } + else + { + if (--phaseOneLength == 0) + { + phase = 2; + affix = suffix; + } + continue; + } + + // Process the digits, decimal, and grouping characters. We + // record five pieces of information. We expect the digits + // to occur in the pattern ####0000.####, and we record the + // number of left digits, zero (central) digits, and right + // digits. The position of the last grouping character is + // recorded (should be somewhere within the first two blocks + // of characters), as is the position of the decimal point, + // if any (should be in the zero digits). If there is no + // decimal point, then there should be no right digits. + if (ch == digit) + { + if (zeroDigitCount > 0) + { + ++digitRightCount; + } + else + { + ++digitLeftCount; + } + if (groupingCount >= 0 && decimalPos < 0) + { + ++groupingCount; + } + } + else if (ch == zeroDigit) + { + if (digitRightCount > 0) + { + throw new IllegalArgumentException( + "Unexpected '0' in pattern \"" + pattern + '"'); + } + ++zeroDigitCount; + if (groupingCount >= 0 && decimalPos < 0) + { + ++groupingCount; + } + } + else if (ch == groupingSeparator) + { + groupingCount = 0; + } + else if (ch == decimalSeparator) + { + if (decimalPos >= 0) + { + throw new IllegalArgumentException( + "Multiple decimal separators in pattern \"" + + pattern + '"'); + } + decimalPos = digitLeftCount + zeroDigitCount + + digitRightCount; + } + else if (ch == exponent) + { + if (useExponentialNotation) + { + throw new IllegalArgumentException("Multiple exponential " + + "symbols in pattern \"" + pattern + '"'); + } + useExponentialNotation = true; + minExponentDigits = 0; + + // Use lookahead to parse out the exponential part + // of the pattern, then jump into phase 2. + while (++pos < pattern.length() + && pattern.charAt(pos) == zeroDigit) + { + ++minExponentDigits; + ++phaseOneLength; + } + + if ((digitLeftCount + zeroDigitCount) < 1 + || minExponentDigits < 1) + { + throw new IllegalArgumentException( + "Malformed exponential " + "pattern \"" + pattern + + '"'); + } + + // Transition to phase 2 + phase = 2; + affix = suffix; + --pos; + continue; + } + else + { + phase = 2; + affix = suffix; + --pos; + --phaseOneLength; + continue; + } + break; + } + } + + // Handle patterns with no '0' pattern character. These patterns + // are legal, but must be interpreted. "##.###" -> "#0.###". + // ".###" -> ".0##". + /* + * We allow patterns of the form "####" to produce a zeroDigitCount of + * zero (got that?); although this seems like it might make it possible + * for format() to produce empty strings, format() checks for this + * condition and outputs a zero digit in this situation. Having a + * zeroDigitCount of zero yields a minimum integer digits of zero, + * which allows proper round-trip patterns. That is, we don't want "#" + * to become "#0" when toPattern() is called (even though that's what + * it really is, semantically). + */ + if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) + { + // Handle "###.###" and "###." and ".###" + int n = decimalPos; + if (n == 0) + { // Handle ".###" + ++n; + } + digitRightCount = digitLeftCount - n; + digitLeftCount = n - 1; + zeroDigitCount = 1; + } + + // Do syntax checking on the digits. + if ((decimalPos < 0 && digitRightCount > 0) + || (decimalPos >= 0 && (decimalPos < digitLeftCount || decimalPos > (digitLeftCount + zeroDigitCount))) + || groupingCount == 0 || inQuote) + { + throw new IllegalArgumentException("Malformed pattern \"" + pattern + + '"'); + } + + if (j == 1) + { + posPrefixPattern = prefix.toString(); + posSuffixPattern = suffix.toString(); + negPrefixPattern = posPrefixPattern; // assume these for now + negSuffixPattern = posSuffixPattern; + int digitTotalCount = digitLeftCount + zeroDigitCount + + digitRightCount; + /* + * The effectiveDecimalPos is the position the decimal is at or + * would be at if there is no decimal. Note that if decimalPos<0, + * then digitTotalCount == digitLeftCount + zeroDigitCount. + */ + int effectiveDecimalPos = decimalPos >= 0 ? decimalPos + : digitTotalCount; + setMinimumIntegerDigits(effectiveDecimalPos - digitLeftCount); + setMaximumIntegerDigits(useExponentialNotation ? digitLeftCount + + getMinimumIntegerDigits() : MAXIMUM_INTEGER_DIGITS); + setMaximumFractionDigits(decimalPos >= 0 ? (digitTotalCount - decimalPos) + : 0); + setMinimumFractionDigits(decimalPos >= 0 ? (digitLeftCount + + zeroDigitCount - decimalPos) : 0); + setGroupingUsed(groupingCount > 0); + this.groupingSize = (groupingCount > 0) ? groupingCount : 0; + this.multiplier = multiplier; + setDecimalSeparatorAlwaysShown(decimalPos == 0 + || decimalPos == digitTotalCount); + } + else + { + negPrefixPattern = prefix.toString(); + negSuffixPattern = suffix.toString(); + gotNegative = true; + } + } + + if (pattern.length() == 0) + { + posPrefixPattern = posSuffixPattern = ""; + setMinimumIntegerDigits(0); + setMaximumIntegerDigits(MAXIMUM_INTEGER_DIGITS); + setMinimumFractionDigits(0); + setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS); + } + + // If there was no negative pattern, or if the negative pattern is + // identical to the positive pattern, then prepend the minus sign to + // the positive pattern to form the negative pattern. + if (!gotNegative + || (negPrefixPattern.equals(posPrefixPattern) && negSuffixPattern + .equals(posSuffixPattern))) + { + negSuffixPattern = posSuffixPattern; + negPrefixPattern = "'-" + posPrefixPattern; + } + + expandAffixes(); + } + + /** + * Sets the maximum number of digits allowed in the integer portion of a + * number. For formatting numbers other than BigInteger and + * BigDecimal objects, the lower of newValue + * and 309 is used. Negative input values are replaced with 0. + * + * @see NumberFormat#setMaximumIntegerDigits + */ + @Override + public void setMaximumIntegerDigits(int newValue) + { + maximumIntegerDigits = Math.min(Math.max(0, newValue), + MAXIMUM_INTEGER_DIGITS); + super + .setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? DOUBLE_INTEGER_DIGITS + : maximumIntegerDigits); + if (minimumIntegerDigits > maximumIntegerDigits) + { + minimumIntegerDigits = maximumIntegerDigits; + super + .setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? DOUBLE_INTEGER_DIGITS + : minimumIntegerDigits); + } + } + + /** + * Sets the minimum number of digits allowed in the integer portion of a + * number. For formatting numbers other than BigInteger and + * BigDecimal objects, the lower of newValue + * and 309 is used. Negative input values are replaced with 0. + * + * @see NumberFormat#setMinimumIntegerDigits + */ + @Override public void setMinimumIntegerDigits(int newValue) + { + minimumIntegerDigits = Math.min(Math.max(0, newValue), + MAXIMUM_INTEGER_DIGITS); + super + .setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? DOUBLE_INTEGER_DIGITS + : minimumIntegerDigits); + if (minimumIntegerDigits > maximumIntegerDigits) + { + maximumIntegerDigits = minimumIntegerDigits; + super + .setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? DOUBLE_INTEGER_DIGITS + : maximumIntegerDigits); + } + } + + /** + * Sets the maximum number of digits allowed in the fraction portion of a + * number. For formatting numbers other than BigInteger and + * BigDecimal objects, the lower of newValue + * and 340 is used. Negative input values are replaced with 0. + * + * @see NumberFormat#setMaximumFractionDigits + */ + @Override public void setMaximumFractionDigits(int newValue) + { + maximumFractionDigits = Math.min(Math.max(0, newValue), + MAXIMUM_FRACTION_DIGITS); + super + .setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ? DOUBLE_FRACTION_DIGITS + : maximumFractionDigits); + if (minimumFractionDigits > maximumFractionDigits) + { + minimumFractionDigits = maximumFractionDigits; + super + .setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ? DOUBLE_FRACTION_DIGITS + : minimumFractionDigits); + } + } + + /** + * Sets the minimum number of digits allowed in the fraction portion of a + * number. For formatting numbers other than BigInteger and + * BigDecimal objects, the lower of newValue + * and 340 is used. Negative input values are replaced with 0. + * + * @see NumberFormat#setMinimumFractionDigits + */ + @Override public void setMinimumFractionDigits(int newValue) + { + minimumFractionDigits = Math.min(Math.max(0, newValue), + MAXIMUM_FRACTION_DIGITS); + super + .setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ? DOUBLE_FRACTION_DIGITS + : minimumFractionDigits); + if (minimumFractionDigits > maximumFractionDigits) + { + maximumFractionDigits = minimumFractionDigits; + super + .setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ? DOUBLE_FRACTION_DIGITS + : maximumFractionDigits); + } + } + + /** + * Gets the maximum number of digits allowed in the integer portion of a + * number. For formatting numbers other than BigInteger and + * BigDecimal objects, the lower of the return value and 309 + * is used. + * + * @see #setMaximumIntegerDigits + */ + @Override public int getMaximumIntegerDigits() + { + return maximumIntegerDigits; + } + + /** + * Gets the minimum number of digits allowed in the integer portion of a + * number. For formatting numbers other than BigInteger and + * BigDecimal objects, the lower of the return value and 309 + * is used. + * + * @see #setMinimumIntegerDigits + */ + @Override public int getMinimumIntegerDigits() + { + return minimumIntegerDigits; + } + + /** + * Gets the maximum number of digits allowed in the fraction portion of a + * number. For formatting numbers other than BigInteger and + * BigDecimal objects, the lower of the return value and 340 + * is used. + * + * @see #setMaximumFractionDigits + */ + @Override public int getMaximumFractionDigits() + { + return maximumFractionDigits; + } + + /** + * Gets the minimum number of digits allowed in the fraction portion of a + * number. For formatting numbers other than BigInteger and + * BigDecimal objects, the lower of the return value and 340 + * is used. + * + * @see #setMinimumFractionDigits + */ + @Override public int getMinimumFractionDigits() + { + return minimumFractionDigits; + } + + /** + * Gets the currency used by this decimal format when formatting currency + * values. The currency is obtained by calling + * {@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency} + * on this number format's symbols. + * + * @return the currency used by this decimal format, or null + * @since 1.4 + */ + @Override public Currency getCurrency() + { + return symbols.getCurrency(); + } + + /** + * Adjusts the minimum and maximum fraction digits to values that are + * reasonable for the currency's default fraction digits. + */ + void adjustForCurrencyDefaultFractionDigits() + { + Currency currency = symbols.getCurrency(); + if (currency == null) + { + try + { + currency = Currency.getInstance(symbols + .getInternationalCurrencySymbol()); + } + catch (IllegalArgumentException e) + { + } + } + if (currency != null) + { + int digits = currency.getDefaultFractionDigits(); + if (digits != -1) + { + int oldMinDigits = getMinimumFractionDigits(); + // Common patterns are "#.##", "#.00", "#". + // Try to adjust all of them in a reasonable way. + if (oldMinDigits == getMaximumFractionDigits()) + { + setMinimumFractionDigits(digits); + setMaximumFractionDigits(digits); + } + else + { + setMinimumFractionDigits(Math.min(digits, oldMinDigits)); + setMaximumFractionDigits(digits); + } + } + } + } + + /** + * Reads the default serializable fields from the stream and performs + * validations and adjustments for older serialized versions. The validations + * and adjustments are: + *

    + *
  1. Verify that the superclass's digit count fields correctly reflect the + * limits imposed on formatting numbers other than BigInteger + * and BigDecimal objects. These limits are stored in the + * superclass for serialization compatibility with older versions, while the + * limits for BigInteger and BigDecimal objects + * are kept in this class. If, in the superclass, the minimum or maximum + * integer digit count is larger than DOUBLE_INTEGER_DIGITS or + * if the minimum or maximum fraction digit count is larger than + * DOUBLE_FRACTION_DIGITS, then the stream data is invalid + * and this method throws an InvalidObjectException. + *
  2. If serialVersionOnStream is less than 3, then call the + * setters for the minimum and maximum integer and fraction digits with the + * values of the corresponding superclass getters to initialize the fields in + * this class. The fields in this class are new with version 3. + *
  3. If serialVersionOnStream is less than 1, indicating + * that the stream was written by JDK 1.1, initialize + * useExponentialNotation to false, since it was not present + * in JDK 1.1. + *
  4. Set serialVersionOnStream to the maximum allowed value + * so that default serialization will work properly if this object is + * streamed out again. + *
+ * + *

+ * Stream versions older than 2 will not have the affix pattern variables + * posPrefixPattern etc. As a result, they will be initialized + * to null, which means the affix strings will be taken as + * literal values. This is exactly what we want, since that corresponds to + * the pre-version-2 behavior. + */ + private void readObject(ObjectInputStream stream) throws IOException, + ClassNotFoundException + { + stream.defaultReadObject(); + + // We only need to check the maximum counts because NumberFormat + // .readObject has already ensured that the maximum is greater than the + // minimum count. + if (super.getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS + || super.getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) + { + throw new InvalidObjectException("Digit count out of range"); + } + if (serialVersionOnStream < 3) + { + setMaximumIntegerDigits(super.getMaximumIntegerDigits()); + setMinimumIntegerDigits(super.getMinimumIntegerDigits()); + setMaximumFractionDigits(super.getMaximumFractionDigits()); + setMinimumFractionDigits(super.getMinimumFractionDigits()); + } + if (serialVersionOnStream < 1) + { + // Didn't have exponential fields + useExponentialNotation = false; + } + serialVersionOnStream = currentSerialVersion; + digitList = new DigitList(); + } + + // ---------------------------------------------------------------------- + // INSTANCE VARIABLES + // ---------------------------------------------------------------------- + + private transient DigitList digitList = new DigitList(); + + /** + * The symbol used as a prefix when formatting positive numbers, e.g. "+". + * + * @serial + * @see #getPositivePrefix + */ + private String positivePrefix = ""; + + /** + * The symbol used as a suffix when formatting positive numbers. This is + * often an empty string. + * + * @serial + * @see #getPositiveSuffix + */ + private String positiveSuffix = ""; + + /** + * The symbol used as a prefix when formatting negative numbers, e.g. "-". + * + * @serial + * @see #getNegativePrefix + */ + private String negativePrefix = "-"; + + /** + * The symbol used as a suffix when formatting negative numbers. This is + * often an empty string. + * + * @serial + * @see #getNegativeSuffix + */ + private String negativeSuffix = ""; + + /** + * The prefix pattern for non-negative numbers. This variable corresponds to + * positivePrefix. + * + *

+ * This pattern is expanded by the method expandAffix() to + * positivePrefix to update the latter to reflect changes in + * symbols. If this variable is null then + * positivePrefix is taken as a literal value that does not + * change when symbols changes. This variable is always + * null for DecimalFormat objects older than + * stream version 2 restored from stream. + * + * @serial + * @since 1.3 + */ + private String posPrefixPattern; + + /** + * The suffix pattern for non-negative numbers. This variable corresponds to + * positiveSuffix. This variable is analogous to + * posPrefixPattern; see that variable for further + * documentation. + * + * @serial + * @since 1.3 + */ + private String posSuffixPattern; + + /** + * The prefix pattern for negative numbers. This variable corresponds to + * negativePrefix. This variable is analogous to + * posPrefixPattern; see that variable for further + * documentation. + * + * @serial + * @since 1.3 + */ + private String negPrefixPattern; + + /** + * The suffix pattern for negative numbers. This variable corresponds to + * negativeSuffix. This variable is analogous to + * posPrefixPattern; see that variable for further + * documentation. + * + * @serial + * @since 1.3 + */ + private String negSuffixPattern; + + /** + * The multiplier for use in percent, per mille, etc. + * + * @serial + * @see #getMultiplier + */ + private int multiplier = 1; + + /** + * The number of digits between grouping separators in the integer portion of + * a number. Must be greater than 0 if NumberFormat.groupingUsed + * is true. + * + * @serial + * @see #getGroupingSize + * @see java.text.NumberFormat#isGroupingUsed + */ + private byte groupingSize = 3; // invariant, + + // > 0 + // if + // useThousands + + /** + * If true, forces the decimal separator to always appear in a formatted + * number, even if the fractional part of the number is zero. + * + * @serial + * @see #isDecimalSeparatorAlwaysShown + */ + private boolean decimalSeparatorAlwaysShown = false; + + /** + * If true, parse returns BigDecimal wherever possible. + * + * @serial + * @see #isParseBigDecimal + * @since 1.5 + */ + private boolean parseBigDecimal = false; + + /** + * True if this object represents a currency format. This determines whether + * the monetary decimal separator is used instead of the normal one. + */ + private transient boolean isCurrencyFormat = false; + + /** + * The DecimalFormatSymbols object used by this format. It + * contains the symbols used to format numbers, e.g. the grouping separator, + * decimal separator, and so on. + * + * @serial + * @see #setDecimalFormatSymbols + * @see java.text.DecimalFormatSymbols + */ + private DecimalFormatSymbols symbols = null; // LIU + + // new + // DecimalFormatSymbols(); + + /** + * True to force the use of exponential (i.e. scientific) notation when + * formatting numbers. + * + * @serial + * @since 1.2 + */ + private boolean useExponentialNotation; // Newly + + // persistent + // in + // the + // Java + // 2 + // platform + + /** + * FieldPositions describing the positive prefix String. This is lazily + * created. Use getPositivePrefixFieldPositions when needed. + */ + private transient FieldPosition[] positivePrefixFieldPositions; + + /** + * FieldPositions describing the positive suffix String. This is lazily + * created. Use getPositiveSuffixFieldPositions when needed. + */ + private transient FieldPosition[] positiveSuffixFieldPositions; + + /** + * FieldPositions describing the negative prefix String. This is lazily + * created. Use getNegativePrefixFieldPositions when needed. + */ + private transient FieldPosition[] negativePrefixFieldPositions; + + /** + * FieldPositions describing the negative suffix String. This is lazily + * created. Use getNegativeSuffixFieldPositions when needed. + */ + private transient FieldPosition[] negativeSuffixFieldPositions; + + /** + * The minimum number of digits used to display the exponent when a number is + * formatted in exponential notation. This field is ignored if + * useExponentialNotation is not true. + * + * @serial + * @since 1.2 + */ + private byte minExponentDigits; // Newly + + // persistent + // in + // the + // Java + // 2 + // platform + + /** + * The maximum number of digits allowed in the integer portion of a + * BigInteger or BigDecimal number. + * maximumIntegerDigits must be greater than or equal to + * minimumIntegerDigits. + * + * @serial + * @see #getMaximumIntegerDigits + * @since 1.5 + */ + private int maximumIntegerDigits = super + .getMaximumIntegerDigits(); + + /** + * The minimum number of digits allowed in the integer portion of a + * BigInteger or BigDecimal number. + * minimumIntegerDigits must be less than or equal to + * maximumIntegerDigits. + * + * @serial + * @see #getMinimumIntegerDigits + * @since 1.5 + */ + private int minimumIntegerDigits = super + .getMinimumIntegerDigits(); + + /** + * The maximum number of digits allowed in the fractional portion of a + * BigInteger or BigDecimal number. + * maximumFractionDigits must be greater than or equal to + * minimumFractionDigits. + * + * @serial + * @see #getMaximumFractionDigits + * @since 1.5 + */ + private int maximumFractionDigits = super + .getMaximumFractionDigits(); + + /** + * The minimum number of digits allowed in the fractional portion of a + * BigInteger or BigDecimal number. + * minimumFractionDigits must be less than or equal to + * maximumFractionDigits. + * + * @serial + * @see #getMinimumFractionDigits + * @since 1.5 + */ + private int minimumFractionDigits = super + .getMinimumFractionDigits(); + + // ---------------------------------------------------------------------- + + static final int currentSerialVersion = 3; + + /** + * The internal serial version which says which version was written. Possible + * values are: + *

    + *
  • 0 (default): versions before the Java 2 platform v1.2 + *
  • 1: version for 1.2, which includes the two new fields + * useExponentialNotation and minExponentDigits. + *
  • 2: version for 1.3 and later, which adds four new fields: + * posPrefixPattern, posSuffixPattern, + * negPrefixPattern, and negSuffixPattern. + *
  • 3: version for 5 and later, which adds five new fields: + * maximumIntegerDigits, minimumIntegerDigits, + * maximumFractionDigits, minimumFractionDigits, + * and parseBigDecimal. + *
+ * + * @since 1.2 + * @serial + */ + private int serialVersionOnStream = currentSerialVersion; + + // ---------------------------------------------------------------------- + // CONSTANTS + // ---------------------------------------------------------------------- + + // Constants for characters used in programmatic (unlocalized) patterns. + private static final char PATTERN_ZERO_DIGIT = '0'; + + private static final char PATTERN_GROUPING_SEPARATOR = ','; + + private static final char PATTERN_DECIMAL_SEPARATOR = '.'; + + private static final char PATTERN_PER_MILLE = '\u2030'; + + private static final char PATTERN_PERCENT = '%'; + + private static final char PATTERN_DIGIT = '#'; + + private static final char PATTERN_SEPARATOR = ';'; + + private static final char PATTERN_EXPONENT = 'E'; + + private static final char PATTERN_MINUS = '-'; + + /** + * The CURRENCY_SIGN is the standard Unicode symbol for currency. It is used + * in patterns and substituted with either the currency symbol, or if it is + * doubled, with the international currency symbol. If the CURRENCY_SIGN is + * seen in a pattern, then the decimal separator is replaced with the + * monetary decimal separator. + * + * The CURRENCY_SIGN is not localized. + */ + private static final char CURRENCY_SIGN = '\u00A4'; + + private static final char QUOTE = '\''; + + private static FieldPosition[] EmptyFieldPositionArray = new FieldPosition[0]; + + // Upper limit on integer and fraction digits for a Java double + static final int DOUBLE_INTEGER_DIGITS = 309; + + static final int DOUBLE_FRACTION_DIGITS = 340; + + // Upper limit on integer and fraction digits for BigDecimal and BigInteger + static final int MAXIMUM_INTEGER_DIGITS = Integer.MAX_VALUE; + + static final int MAXIMUM_FRACTION_DIGITS = Integer.MAX_VALUE; + + // Proclaim JDK 1.1 serial compatibility. + static final long serialVersionUID = 864413376551465018L; +} diff --git a/simplCore/src/ecologylab/generic/text/Format.java b/simplCore/src/ecologylab/generic/text/Format.java index 8405d93a..2c69b5e9 100644 --- a/simplCore/src/ecologylab/generic/text/Format.java +++ b/simplCore/src/ecologylab/generic/text/Format.java @@ -1,407 +1,407 @@ -/* - * @(#)Format.java 1.34 03/12/19 - * - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - */ - -/* - * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved - * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved - * - * The original version of this source code and documentation is copyrighted - * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These - * materials are provided under terms of a License Agreement between Taligent - * and Sun. This technology is protected by multiple US and International - * patents. This notice and attribution to Taligent may not be removed. - * Taligent is a registered trademark of Taligent, Inc. - * - */ -package ecologylab.generic.text; - -import java.io.Serializable; -import java.text.AttributedCharacterIterator; -import java.text.AttributedString; -import java.text.DateFormat; -import java.text.FieldPosition; -import java.text.ParseException; -import java.text.ParsePosition; - -/** - * Format is an abstract base class for formatting - * locale-sensitive information such as dates, messages, and numbers. - * - *

- * Format defines the programming interface for formatting - * locale-sensitive objects into Strings (the - * format method) and for parsing Strings back - * into objects (the parseObject method). - * - *

- * Generally, a format's parseObject method must be able to parse - * any string formatted by its format method. However, there may - * be exceptional cases where this is not possible. For example, a - * format method might create two adjacent integer numbers with - * no separator in between, and in this case the parseObject - * could not tell which digits belong to which number. - * - *

Subclassing

- * - *

- * The Java 2 platform provides three specialized subclasses of - * Format-- DateFormat, - * MessageFormat, and NumberFormat--for - * formatting dates, messages, and numbers, respectively. - *

- * Concrete subclasses must implement three methods: - *

    - *
  1. - * format(Object obj, StringBuffer toAppendTo, FieldPosition pos) - *
  2. formatToCharacterIterator(Object obj) - *
  3. parseObject(String source, ParsePosition pos) - *
- * These general methods allow polymorphic parsing and formatting of objects and - * are used, for example, by MessageFormat. Subclasses often - * also provide additional format methods for specific input - * types as well as parse methods for specific result types. Any - * parse method that does not take a ParsePosition - * argument should throw ParseException when no text in the - * required format is at the beginning of the input text. - * - *

- * Most subclasses will also implement the following factory methods: - *

    - *
  1. getInstance for getting a useful format object - * appropriate for the current locale - *
  2. getInstance(Locale) for getting a useful format object - * appropriate for the specified locale - *
- * In addition, some subclasses may also implement other - * getXxxxInstance methods for more specialized control. For - * example, the NumberFormat class provides - * getPercentInstance and getCurrencyInstance - * methods for getting specialized number formatters. - * - *

- * Subclasses of Format that allow programmers to create objects - * for locales (with getInstance(Locale) for example) must also - * implement the following class method:

- * - *
- * public static Locale[] getAvailableLocales()
- * 
- * - *
- * - *

- * And finally subclasses may define a set of constants to identify the various - * fields in the formatted output. These constants are used to create a - * FieldPosition object which identifies what information is contained in the - * field and its position in the formatted result. These constants should be - * named item_FIELD where item - * identifies the field. For examples of these constants, see - * ERA_FIELD and its friends in {@link DateFormat}. - * - *

Synchronization

- * - *

- * Formats are generally not synchronized. It is recommended to create separate - * format instances for each thread. If multiple threads access a format - * concurrently, it must be synchronized externally. - * - * @see java.text.ParsePosition - * @see java.text.FieldPosition - * @see java.text.NumberFormat - * @see java.text.DateFormat - * @see java.text.MessageFormat - * @version 1.34, 12/19/03 - * @author Mark Davis - */ -public abstract class Format implements Serializable, Cloneable -{ - - private static final long serialVersionUID = -299282585814624189L; - - /** - * Formats an object to produce a string. This is equivalent to

- * {@link #format(Object, StringBuffer, FieldPosition) format}(obj, - * new StringBuffer(), new FieldPosition(0)).toString(); - *
- * - * @param obj - * The object to format - * @return Formatted string. - * @exception IllegalArgumentException - * if the Format cannot format the given object - */ - public final String format(Object obj) - { - return format(obj, new StringBuffer(), new FieldPosition(0)).toString(); - } - - /** - * Formats an object and appends the resulting text to a given string buffer. - * If the pos argument identifies a field used by the format, - * then its indices are set to the beginning and end of the first such field - * encountered. - * - * @param obj - * The object to format - * @param toAppendTo - * where the text is to be appended - * @param pos - * A FieldPosition identifying a field in the - * formatted text - * @return the string buffer passed in as toAppendTo, with - * formatted text appended - * @exception NullPointerException - * if toAppendTo or pos is null - * @exception IllegalArgumentException - * if the Format cannot format the given object - */ - public abstract StringBuffer format(Object obj, StringBuffer toAppendTo, - FieldPosition pos); - - /** - * Formats an Object producing an AttributedCharacterIterator. - * You can use the returned AttributedCharacterIterator to - * build the resulting String, as well as to determine information about the - * resulting String. - *

- * Each attribute key of the AttributedCharacterIterator will be of type - * Field. It is up to each Format - * implementation to define what the legal values are for each attribute in - * the AttributedCharacterIterator, but typically the - * attribute key is also used as the attribute value. - *

- * The default implementation creates an - * AttributedCharacterIterator with no attributes. Subclasses - * that support fields should override this and create an - * AttributedCharacterIterator with meaningful attributes. - * - * @exception NullPointerException - * if obj is null. - * @exception IllegalArgumentException - * when the Format cannot format the given object. - * @param obj - * The object to format - * @return AttributedCharacterIterator describing the formatted value. - * @since 1.4 - */ - public AttributedCharacterIterator formatToCharacterIterator(Object obj) - { - return createAttributedCharacterIterator(format(obj)); - } - - /** - * Parses text from a string to produce an object. - *

- * The method attempts to parse text starting at the index given by - * pos. If parsing succeeds, then the index of - * pos is updated to the index after the last character used - * (parsing does not necessarily use all characters up to the end of the - * string), and the parsed object is returned. The updated pos - * can be used to indicate the starting point for the next call to this - * method. If an error occurs, then the index of pos is not - * changed, the error index of pos is set to the index of the - * character where the error occurred, and null is returned. - * - * @param source - * A String, part of which should be parsed. - * @param pos - * A ParsePosition object with index and error index - * information as described above. - * @return An Object parsed from the string. In case of error, - * returns null. - * @exception NullPointerException - * if pos is null. - */ - public abstract Object parseObject(String source, ParsePosition pos); - - /** - * Parses text from the beginning of the given string to produce an object. - * The method may not use the entire text of the given string. - * - * @param source - * A String whose beginning should be parsed. - * @return An Object parsed from the string. - * @exception ParseException - * if the beginning of the specified string cannot be parsed. - */ - public Object parseObject(String source) throws ParseException - { - ParsePosition pos = new ParsePosition(0); - Object result = parseObject(source, pos); - if (pos.getIndex() == 0) - { - throw new ParseException("Format.parseObject(String) failed", pos - .getErrorIndex()); - } - return result; - } - - /** - * Creates and returns a copy of this object. - * - * @return a clone of this instance. - */ - @Override - public Object clone() - { - try - { - return super.clone(); - } - catch (CloneNotSupportedException e) - { - // will never happen - return null; - } - } - - // - // Convenience methods for creating AttributedCharacterIterators from - // different parameters. - // - - /** - * Creates an AttributedCharacterIterator for the String - * s. - * - * @param s - * String to create AttributedCharacterIterator from - * @return AttributedCharacterIterator wrapping s - */ - AttributedCharacterIterator createAttributedCharacterIterator(String s) - { - AttributedString as = new AttributedString(s); - - return as.getIterator(); - } - - /** - * Returns an AttributedCharacterIterator with the String string - * and additional key/value pair key, value. - * - * @param string - * String to create AttributedCharacterIterator from - * @param key - * Key for AttributedCharacterIterator - * @param value - * Value associated with key in AttributedCharacterIterator - * @return AttributedCharacterIterator wrapping args - */ - AttributedCharacterIterator createAttributedCharacterIterator(String string, - AttributedCharacterIterator.Attribute key, Object value) - { - AttributedString as = new AttributedString(string); - - as.addAttribute(key, value); - return as.getIterator(); - } - - /** - * Creates an AttributedCharacterIterator with the contents of - * iterator and the additional attribute key - * value. - * - * @param iterator - * Initial AttributedCharacterIterator to add arg to - * @param key - * Key for AttributedCharacterIterator - * @param value - * Value associated with key in AttributedCharacterIterator - * @return AttributedCharacterIterator wrapping args - */ - AttributedCharacterIterator createAttributedCharacterIterator( - AttributedCharacterIterator iterator, - AttributedCharacterIterator.Attribute key, Object value) - { - AttributedString as = new AttributedString(iterator); - - as.addAttribute(key, value); - return as.getIterator(); - } - - /** - * Defines constants that are used as attribute keys in the - * AttributedCharacterIterator returned from - * Format.formatToCharacterIterator and as field identifiers - * in FieldPosition. - * - * @since 1.4 - */ - public static class Field extends AttributedCharacterIterator.Attribute - { - - // Proclaim serial compatibility with 1.4 FCS - private static final long serialVersionUID = 276966692217360283L; - - /** - * Creates a Field with the specified name. - * - * @param name - * Name of the attribute - */ - protected Field(String name) - { - super(name); - } - } - - /** - * FieldDelegate is notified by the various Format - * implementations as they are formatting the Objects. This allows for - * storage of the individual sections of the formatted String for later use, - * such as in a FieldPosition or for an - * AttributedCharacterIterator. - *

- * Delegates should NOT assume that the Format will notify the - * delegate of fields in any particular order. - * - * @see FieldPosition.Delegate - * @see CharacterIteratorFieldDelegate - */ - interface FieldDelegate - { - /** - * Notified when a particular region of the String is formatted. This - * method will be invoked if there is no corresponding integer field id - * matching attr. - * - * @param attr - * Identifies the field matched - * @param value - * Value associated with the field - * @param start - * Beginning location of the field, will be >= 0 - * @param end - * End of the field, will be >= start and <= buffer.length() - * @param buffer - * Contains current formatted value, receiver should NOT modify - * it. - */ - public void formatted(Format.Field attr, Object value, int start, - int end, StringBuffer buffer); - - /** - * Notified when a particular region of the String is formatted. - * - * @param fieldID - * Identifies the field by integer - * @param attr - * Identifies the field matched - * @param value - * Value associated with the field - * @param start - * Beginning location of the field, will be >= 0 - * @param end - * End of the field, will be >= start and <= buffer.length() - * @param buffer - * Contains current formatted value, receiver should NOT modify - * it. - */ - public void formatted(int fieldID, Format.Field attr, Object value, - int start, int end, StringBuffer buffer); - } -} +/* + * @(#)Format.java 1.34 03/12/19 + * + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +/* + * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved + * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved + * + * The original version of this source code and documentation is copyrighted + * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These + * materials are provided under terms of a License Agreement between Taligent + * and Sun. This technology is protected by multiple US and International + * patents. This notice and attribution to Taligent may not be removed. + * Taligent is a registered trademark of Taligent, Inc. + * + */ +package ecologylab.generic.text; + +import java.io.Serializable; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.text.DateFormat; +import java.text.FieldPosition; +import java.text.ParseException; +import java.text.ParsePosition; + +/** + * Format is an abstract base class for formatting + * locale-sensitive information such as dates, messages, and numbers. + * + *

+ * Format defines the programming interface for formatting + * locale-sensitive objects into Strings (the + * format method) and for parsing Strings back + * into objects (the parseObject method). + * + *

+ * Generally, a format's parseObject method must be able to parse + * any string formatted by its format method. However, there may + * be exceptional cases where this is not possible. For example, a + * format method might create two adjacent integer numbers with + * no separator in between, and in this case the parseObject + * could not tell which digits belong to which number. + * + *

Subclassing

+ * + *

+ * The Java 2 platform provides three specialized subclasses of + * Format-- DateFormat, + * MessageFormat, and NumberFormat--for + * formatting dates, messages, and numbers, respectively. + *

+ * Concrete subclasses must implement three methods: + *

    + *
  1. + * format(Object obj, StringBuffer toAppendTo, FieldPosition pos) + *
  2. formatToCharacterIterator(Object obj) + *
  3. parseObject(String source, ParsePosition pos) + *
+ * These general methods allow polymorphic parsing and formatting of objects and + * are used, for example, by MessageFormat. Subclasses often + * also provide additional format methods for specific input + * types as well as parse methods for specific result types. Any + * parse method that does not take a ParsePosition + * argument should throw ParseException when no text in the + * required format is at the beginning of the input text. + * + *

+ * Most subclasses will also implement the following factory methods: + *

    + *
  1. getInstance for getting a useful format object + * appropriate for the current locale + *
  2. getInstance(Locale) for getting a useful format object + * appropriate for the specified locale + *
+ * In addition, some subclasses may also implement other + * getXxxxInstance methods for more specialized control. For + * example, the NumberFormat class provides + * getPercentInstance and getCurrencyInstance + * methods for getting specialized number formatters. + * + *

+ * Subclasses of Format that allow programmers to create objects + * for locales (with getInstance(Locale) for example) must also + * implement the following class method:

+ * + *
+ * public static Locale[] getAvailableLocales()
+ * 
+ * + *
+ * + *

+ * And finally subclasses may define a set of constants to identify the various + * fields in the formatted output. These constants are used to create a + * FieldPosition object which identifies what information is contained in the + * field and its position in the formatted result. These constants should be + * named item_FIELD where item + * identifies the field. For examples of these constants, see + * ERA_FIELD and its friends in {@link DateFormat}. + * + *

Synchronization

+ * + *

+ * Formats are generally not synchronized. It is recommended to create separate + * format instances for each thread. If multiple threads access a format + * concurrently, it must be synchronized externally. + * + * @see java.text.ParsePosition + * @see java.text.FieldPosition + * @see java.text.NumberFormat + * @see java.text.DateFormat + * @see java.text.MessageFormat + * @version 1.34, 12/19/03 + * @author Mark Davis + */ +public abstract class Format implements Serializable, Cloneable +{ + + private static final long serialVersionUID = -299282585814624189L; + + /** + * Formats an object to produce a string. This is equivalent to

+ * {@link #format(Object, StringBuffer, FieldPosition) format}(obj, + * new StringBuffer(), new FieldPosition(0)).toString(); + *
+ * + * @param obj + * The object to format + * @return Formatted string. + * @exception IllegalArgumentException + * if the Format cannot format the given object + */ + public final String format(Object obj) + { + return format(obj, new StringBuffer(), new FieldPosition(0)).toString(); + } + + /** + * Formats an object and appends the resulting text to a given string buffer. + * If the pos argument identifies a field used by the format, + * then its indices are set to the beginning and end of the first such field + * encountered. + * + * @param obj + * The object to format + * @param toAppendTo + * where the text is to be appended + * @param pos + * A FieldPosition identifying a field in the + * formatted text + * @return the string buffer passed in as toAppendTo, with + * formatted text appended + * @exception NullPointerException + * if toAppendTo or pos is null + * @exception IllegalArgumentException + * if the Format cannot format the given object + */ + public abstract StringBuffer format(Object obj, StringBuffer toAppendTo, + FieldPosition pos); + + /** + * Formats an Object producing an AttributedCharacterIterator. + * You can use the returned AttributedCharacterIterator to + * build the resulting String, as well as to determine information about the + * resulting String. + *

+ * Each attribute key of the AttributedCharacterIterator will be of type + * Field. It is up to each Format + * implementation to define what the legal values are for each attribute in + * the AttributedCharacterIterator, but typically the + * attribute key is also used as the attribute value. + *

+ * The default implementation creates an + * AttributedCharacterIterator with no attributes. Subclasses + * that support fields should override this and create an + * AttributedCharacterIterator with meaningful attributes. + * + * @exception NullPointerException + * if obj is null. + * @exception IllegalArgumentException + * when the Format cannot format the given object. + * @param obj + * The object to format + * @return AttributedCharacterIterator describing the formatted value. + * @since 1.4 + */ + public AttributedCharacterIterator formatToCharacterIterator(Object obj) + { + return createAttributedCharacterIterator(format(obj)); + } + + /** + * Parses text from a string to produce an object. + *

+ * The method attempts to parse text starting at the index given by + * pos. If parsing succeeds, then the index of + * pos is updated to the index after the last character used + * (parsing does not necessarily use all characters up to the end of the + * string), and the parsed object is returned. The updated pos + * can be used to indicate the starting point for the next call to this + * method. If an error occurs, then the index of pos is not + * changed, the error index of pos is set to the index of the + * character where the error occurred, and null is returned. + * + * @param source + * A String, part of which should be parsed. + * @param pos + * A ParsePosition object with index and error index + * information as described above. + * @return An Object parsed from the string. In case of error, + * returns null. + * @exception NullPointerException + * if pos is null. + */ + public abstract Object parseObject(String source, ParsePosition pos); + + /** + * Parses text from the beginning of the given string to produce an object. + * The method may not use the entire text of the given string. + * + * @param source + * A String whose beginning should be parsed. + * @return An Object parsed from the string. + * @exception ParseException + * if the beginning of the specified string cannot be parsed. + */ + public Object parseObject(String source) throws ParseException + { + ParsePosition pos = new ParsePosition(0); + Object result = parseObject(source, pos); + if (pos.getIndex() == 0) + { + throw new ParseException("Format.parseObject(String) failed", pos + .getErrorIndex()); + } + return result; + } + + /** + * Creates and returns a copy of this object. + * + * @return a clone of this instance. + */ + @Override + public Object clone() + { + try + { + return super.clone(); + } + catch (CloneNotSupportedException e) + { + // will never happen + return null; + } + } + + // + // Convenience methods for creating AttributedCharacterIterators from + // different parameters. + // + + /** + * Creates an AttributedCharacterIterator for the String + * s. + * + * @param s + * String to create AttributedCharacterIterator from + * @return AttributedCharacterIterator wrapping s + */ + AttributedCharacterIterator createAttributedCharacterIterator(String s) + { + AttributedString as = new AttributedString(s); + + return as.getIterator(); + } + + /** + * Returns an AttributedCharacterIterator with the String string + * and additional key/value pair key, value. + * + * @param string + * String to create AttributedCharacterIterator from + * @param key + * Key for AttributedCharacterIterator + * @param value + * Value associated with key in AttributedCharacterIterator + * @return AttributedCharacterIterator wrapping args + */ + AttributedCharacterIterator createAttributedCharacterIterator(String string, + AttributedCharacterIterator.Attribute key, Object value) + { + AttributedString as = new AttributedString(string); + + as.addAttribute(key, value); + return as.getIterator(); + } + + /** + * Creates an AttributedCharacterIterator with the contents of + * iterator and the additional attribute key + * value. + * + * @param iterator + * Initial AttributedCharacterIterator to add arg to + * @param key + * Key for AttributedCharacterIterator + * @param value + * Value associated with key in AttributedCharacterIterator + * @return AttributedCharacterIterator wrapping args + */ + AttributedCharacterIterator createAttributedCharacterIterator( + AttributedCharacterIterator iterator, + AttributedCharacterIterator.Attribute key, Object value) + { + AttributedString as = new AttributedString(iterator); + + as.addAttribute(key, value); + return as.getIterator(); + } + + /** + * Defines constants that are used as attribute keys in the + * AttributedCharacterIterator returned from + * Format.formatToCharacterIterator and as field identifiers + * in FieldPosition. + * + * @since 1.4 + */ + public static class Field extends AttributedCharacterIterator.Attribute + { + + // Proclaim serial compatibility with 1.4 FCS + private static final long serialVersionUID = 276966692217360283L; + + /** + * Creates a Field with the specified name. + * + * @param name + * Name of the attribute + */ + protected Field(String name) + { + super(name); + } + } + + /** + * FieldDelegate is notified by the various Format + * implementations as they are formatting the Objects. This allows for + * storage of the individual sections of the formatted String for later use, + * such as in a FieldPosition or for an + * AttributedCharacterIterator. + *

+ * Delegates should NOT assume that the Format will notify the + * delegate of fields in any particular order. + * + * @see FieldPosition.Delegate + * @see CharacterIteratorFieldDelegate + */ + interface FieldDelegate + { + /** + * Notified when a particular region of the String is formatted. This + * method will be invoked if there is no corresponding integer field id + * matching attr. + * + * @param attr + * Identifies the field matched + * @param value + * Value associated with the field + * @param start + * Beginning location of the field, will be >= 0 + * @param end + * End of the field, will be >= start and <= buffer.length() + * @param buffer + * Contains current formatted value, receiver should NOT modify + * it. + */ + public void formatted(Format.Field attr, Object value, int start, + int end, StringBuffer buffer); + + /** + * Notified when a particular region of the String is formatted. + * + * @param fieldID + * Identifies the field by integer + * @param attr + * Identifies the field matched + * @param value + * Value associated with the field + * @param start + * Beginning location of the field, will be >= 0 + * @param end + * End of the field, will be >= start and <= buffer.length() + * @param buffer + * Contains current formatted value, receiver should NOT modify + * it. + */ + public void formatted(int fieldID, Format.Field attr, Object value, + int start, int end, StringBuffer buffer); + } +} diff --git a/simplCore/src/ecologylab/io/Assets.java b/simplCore/src/ecologylab/io/Assets.java index 5ba230e6..14b1a279 100644 --- a/simplCore/src/ecologylab/io/Assets.java +++ b/simplCore/src/ecologylab/io/Assets.java @@ -1,549 +1,549 @@ -/** - * The Assets class is used to manage cachable assets. - */ -package ecologylab.io; - -import java.io.File; -import java.net.URLEncoder; - -import ecologylab.appframework.ApplicationEnvironment; -import ecologylab.appframework.ApplicationProperties; -import ecologylab.appframework.Environment; -import ecologylab.appframework.EnvironmentGeneric; -import ecologylab.appframework.PropertiesAndDirectories; -import ecologylab.appframework.SingletonApplicationEnvironment; -import ecologylab.appframework.StatusReporter; -import ecologylab.appframework.types.AssetState; -import ecologylab.appframework.types.AssetsState; -import ecologylab.appframework.types.AssetsTranslations; -import ecologylab.generic.Debug; -import ecologylab.generic.StringBuilderPool; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.Format; - -/** - * Used to manage cachable assets. - *

- * This class must not be called until codeBase is properly set! - *

- * Here's how it works: (1) There is a file called assets.xml. It lives only in - * applicationDataDir(), the cache root. There is *no* version of this file in - * /config/preferences, the assets root. - * - * This file stores the *current* cached version # of each asset. - * - * (2) The version of each Asset is a constant, which lives *in the code*. It is passed to - * Assets.downloadZip(). (3) If there is no local versions of assets.xml (first time ap is run), or - * if any version turns out to be stale, the assets.xml file will need to be written to the cache - * root. The application *must* call updateAssetsXml() to do this, after it is finished reading all - * Assets. This method will know if writing the file is needed or not. - * - * @author blake - * @author andruid - */ -public class Assets extends Debug implements ApplicationProperties -{ - /** - * Source URL root of the tree of assets for this application. Default is the configDir(), which - * in turn is the config subdir of codebase. - * - * - * The source location of any asset is specified relative to here. - */ - static ParsedURL assetsRoot; - - protected static final String ASSETS_XML_NAME = "assets.xml"; - - static File assetsXmlFile; - - /** - * Asset version number info! - */ - static AssetsState assetsState; - - static boolean needToWriteAssetsXml; - - /** - * The root directory on the local machine where assets will be stored (cached). - * - * The cache destination of any asset is applied relative to here. - */ - static File cacheRoot; - - /* - * Set-up assets and cache roots. Read currently downloaded - */ - static - { - cacheRoot = /* - * ApplicationEnvironment.runningInEclipse() ? EnvironmentGeneric.configDir().file() - * : - */PropertiesAndDirectories.thisApplicationDir(); - - assetsXmlFile = new File(cacheRoot, ASSETS_XML_NAME); - if (assetsXmlFile.exists()) - { - try - { - assetsState = (AssetsState) AssetsTranslations.get().deserialize(assetsXmlFile, Format.XML); - - } - catch (SIMPLTranslationException e) - { - println("ERROR reading AssetsState from " + assetsXmlFile); - e.printStackTrace(); - } - } - else - { - println("Assets: no cached assets found at " + assetsXmlFile); - } - if (assetsState == null) - assetsState = new AssetsState(); - } - - // //////////////////////////////////////////////////////////// - - /** - * No instances possible, static references only. - */ - private Assets() - { - } - - /** - * Given a relative path, return a file reference to this path from the cache root. - * - * @param relativePath - * A string representing the relative file path. - * @return A file reference to the requested path - */ - public static File getAsset(String relativePath) - { - if (cacheRoot == null) - return null; - - return new File(cacheRoot.getAbsolutePath() + File.separatorChar + relativePath); - } - - /** - * Same as getAsset(String), but allows additional relative file/directory to be specified against - * the relativePath - * - * @param relativePath - * A string representing the relative file path - * @param additionalContext - * A string representing an additional relative path. This path is relative to the - * relativePath parameter (rather than the cache root). - * @return A file reference to the requested path - */ - public static File getAsset(String relativePath, String additionalContext) - { - if (cacheRoot == null) - return null; - - return new File(getAsset(relativePath), additionalContext); - } - - /** - * Same as getAsset(String), but creates the Asset location if it doesn't exist - * - * @param relativePath - * A string representing the relative file path. - * @return A file reference tot he requested path - */ - public static File getAndPerhapsCreateAsset(String relativePath) - { - File theAsset = getAsset(relativePath); - - if (!theAsset.exists()) - theAsset.mkdirs(); - - return theAsset; - } - - /** - * Same as getAndPerhapsCreateAsset(String, String), but creates the Asset location if it doesn't - * exist - * - * @param relativePath - * A string representing the relative file path. - * @param additionalContext - * A string representing an additional relative path. This path is relative to the - * relativePath parameter (rather than the cache root). - * - * @return A file reference to the requested path - * @see #getAsset(String, String) - */ - public static File getAndPerhapsCreateAsset(String relativePath, String additionalContext) - { - File theAsset = getAsset(relativePath, additionalContext); - - if (!theAsset.exists()) - theAsset.mkdirs(); - - return theAsset; - } - - public static File getAsset(AssetsRoot assetsRoot, String relativePath) - { - return Files.newFile(assetsRoot.getCacheRoot(), relativePath); - } - - public static File getAsset(AssetsRoot assetsRoot, String relativePath, String assetName, - StatusReporter status, boolean forceDownload, float version) - { - File result = relativePath != null ? getAsset(assetsRoot, relativePath) - : assetsRoot.getCacheRoot(); - if (!SingletonApplicationEnvironment.runningInEclipse()) - downloadZip(assetsRoot, assetName, status, forceDownload, version); - - return result; - } - - /** - * Version of getAsset that uses a non-singleton ApplicationEnvironment to know where to store - * assets. - * - * @param assetsRoot - * @param relativePath - * @param assetName - * @param status - * @param forceDownload - * @param version - * @param env - * @return - */ - public static File getAsset(AssetsRoot assetsRoot, String relativePath, String assetName, - StatusReporter status, boolean forceDownload, float version, ApplicationEnvironment env) - { - File result = relativePath != null ? getAsset(assetsRoot, relativePath) - : assetsRoot.getCacheRoot(); - if (!env.isRunningInEclipse()) - downloadZip(assetsRoot, assetName, status, forceDownload, version); - - return result; - } - - public static void downloadZip(ParsedURL sourceZip, File targetFile, boolean forceDownload, - float version) - { - downloadZip(sourceZip, targetFile, null, forceDownload, version); - } - - public static void downloadZip(AssetsRoot assetsRoot, String assetName, StatusReporter status, - boolean forceDownload, float version) - { - downloadZip(assetsRoot.getAssetRoot().getRelative(assetName + ".zip", "forming zip location"), - assetsRoot.getCacheRoot(), - status, - forceDownload, - version); - } - - /** - * Download and uncompress a zip file from a source to a target location with minimal effort, - * unless the zip file already exists at the target location, in which case, do nothing. - * - * @param status - * The Status object that provides a source of state change visibility; can be null. - * @param forceDownload - * @param version - */ - public static void downloadZip(ParsedURL sourceZip, File targetDir, StatusReporter status, - boolean forceDownload, float version) - { - String zipFileName = sourceZip.url().getFile(); - int lastSlash = zipFileName.lastIndexOf('\\'); - if (lastSlash == -1) - lastSlash = zipFileName.lastIndexOf('/'); - - zipFileName = zipFileName.substring(lastSlash + 1); - File zipFileDestination = Files.newFile(targetDir, zipFileName); - if (forceDownload || !zipFileDestination.canRead() - || !localVersionIsUpToDate(zipFileName, version)) - { - if (targetDir.exists()) - Files.deleteDirectory(targetDir); - ZipDownload downloadingZip = ZipDownload.downloadAndPerhapsUncompress(sourceZip, - targetDir, - status, - true); - - Debug.println("downloading zip: " + downloadingZip.toString()); - - if (downloadingZip != null) // null if already available locally or error - { - downloadingZip.waitForDownload(); - } - } - else - println("Using cached " + zipFileDestination); - } - - /** - * Get the source URL root of the tree of assets for this application. Default is the configDir(), - * which in turn is the config subdir of codebase. - * - * @return ParsedURL referring to the root of the remote place we download assets from. - */ - public static ParsedURL assetsRoot() - { - return EnvironmentGeneric.configDir(); - } - - /** - * Get the source URL root of the tree of assets for this application. Default is the configDir(), - * which in turn is the config subdir of codebase. - * - * @return ParsedURL referring to the root of the remote place we download assets from. - */ - public static ParsedURL assetsRoot(Environment e) - { - return EnvironmentGeneric.configDir(e); - } - - /** - * Get the root file path for caching. Assets are specified relative to this path. - * - * @return - */ - public static File cacheRoot() - { - return cacheRoot; - } - - /** - * Download XML from the sourcePath, within the assetsRoot (the application's config dir), to the - * target path within the applicationDir. - * - * @param sourcePath - * @param targetPath - * @param status - */ - public static void downloadXML(String sourcePath, String targetPath, StatusReporter status) - { - File targetDir = cacheRoot(); - if ((targetPath != null) && (targetPath.length() > 0)) - targetDir = Files.newFile(targetDir, targetPath); - - downloadXML(assetsRoot().getRelative(sourcePath, "forming Asset path location"), - targetDir, - status); - } - - /** - * Download XML from the sourcePath, within the assetsRoot (the application's config dir), to the - * target path within the applicationDir. - * - * @param sourcePath - * @param targetPath - * @param status - */ - public static void downloadXML(Environment e, String sourcePath, String targetPath, - StatusReporter status) - { - File targetDir = cacheRoot(); - if ((targetPath != null) && (targetPath.length() > 0)) - targetDir = Files.newFile(targetDir, targetPath); - - downloadXML(EnvironmentGeneric.configDir(e).getRelative(sourcePath, - "forming Asset path location"), - targetDir, - status); - } - - /** - * Download an XML file from a source to a target location with minimal effort, unless the XML - * file already exists at the target location, in which case, do nothing. - * - * @param status - * The Status object that provides a source of state change visiblity; can be null. - * @param sourceXML - * The location of the zip file to download and uncompress. - * @param targetDir - * The location where the zip file should be uncompressed. This directory structure will - * be created if it doesn't exist. - */ - public static void downloadXML(ParsedURL sourceXML, File targetDir, StatusReporter status) - { - String xmlFileName = sourceXML.url().getFile(); - int lastSlash = xmlFileName.lastIndexOf('\\'); - if (lastSlash == -1) - lastSlash = xmlFileName.lastIndexOf('/'); - - xmlFileName = xmlFileName.substring(lastSlash + 1); - File xmlFileDestination = Files.newFile(targetDir, xmlFileName); - - if (!xmlFileDestination.canRead()) - { - // we just want to download it, not uncompress it... (using code from zip downloading stuff) - ZipDownload downloadingZip = ZipDownload.downloadAndPerhapsUncompress(sourceXML, - targetDir, - status, - false); - if (downloadingZip != null) // null if already available locally or error - { - downloadingZip.waitForDownload(); - } - } - else - println("Using cached " + xmlFileDestination); - } - - static public final float IGNORE_VERSION = 0f; - - /** - * Determines if a file should be downloaded again, based upon it's file version. - * - * @param id - * the name of the file to check - * @param requiredVersion - * the version of that file \ - * @return false if the local asset is stale and to download true if the local version is fine and - * we dont need to download - */ - public static boolean localVersionIsUpToDate(String id, float requiredVersion) - { - if (requiredVersion == IGNORE_VERSION) - return true; - - AssetState assetState = assetsState.lookup(id); - boolean result = assetState != null; - if (result) - { - float localVersion = assetState.getVersion(); - result = requiredVersion <= localVersion; - } - else - { // create an entry to write later when the application developer calls updateAssetsXml(). - assetState = assetsState.update(id); - } - if (!result) - { - needToWriteAssetsXml = true; - assetState.setVersion(requiredVersion); // update the version in our data structure - } - - return result; - } - - /** - * When necessary, re-write the local (and only) assets.xml file. - * - */ - public static void updateAssetsXml(String sourceSpot) - { - try - { - sourceSpot = " from " + sourceSpot; - if (needToWriteAssetsXml) - { - needToWriteAssetsXml = false; - // assetsState.translateToXML(assetsXmlFile); - - SimplTypesScope.serialize(assetsState, assetsXmlFile, Format.XML); - - println("Saved Assets XML" + sourceSpot + ": " + assetsXmlFile); - } - else - println("NO NEED to Save Assets XML" + sourceSpot + ": " + assetsXmlFile); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - } - - private static final StringBuilderPool stringPool = new StringBuilderPool(2, 255); - - /** - * Derive a non-duplicate cache filename given a ParsedURL location - * - * @param location - * The location of the file to be cached. - * @param directory - * The directory to cache the file - * @param additional - * An additional text to add to the end of the filename, but before the extension - * @param separator - * Separator used to divide sections of filename (e.g. "-", ".") - * @param extension - * Extension to add to file name if it doesn't already exist - * - * @return A string containing the new filename - */ - @SuppressWarnings("deprecation") - public static String getCacheFilename(ParsedURL location, File directory, String additional, - String separator, String extension) - { - StringBuilder filename = stringPool.nextBuffer(); - filename.append(location.host()); - filename.append(separator); - String locationString = location.url().getPath(); - String query = location.url().getQuery(); - filename.append(locationString.substring(locationString.lastIndexOf('/') + 1)); - if (query != null && query.length() > 0) - { - filename.append("%3F"); - filename.append(URLEncoder.encode(query)); - } - - if (additional != null) - { - filename.append(separator); - filename.append(additional); - } - - if (extension != null && !locationString.endsWith(extension)) - { - filename.append("."); - filename.append(extension); - } - - String filenameString = filename.toString(); - // File localFile = new File(directory, filename.toString()); - // if (localFile.exists()) - // { - // int extensionStart = filename.lastIndexOf("."); - // int count = 1; - // String pre = filename.substring(0, extensionStart); - // String end = filename.substring(extensionStart); - // - // while(localFile.exists()) - // { - // StringBuilder newFilename = stringPool.nextBuffer(); - // newFilename.append(pre); - // newFilename.append(separator); - // newFilename.append(count); - // newFilename.append(end); - // filenameString = newFilename.toString(); - // localFile = new File(directory, filenameString); - // count++; - // stringPool.release(newFilename); - // } - // stringPool.release(filename); - // } - - return filenameString; - } - - /** - * @return the assetsRoot - */ - public static ParsedURL getAssetsRoot() - { - return assetsRoot; - } - - /** - * @return the cacheRoot - */ - public static File getCacheRoot() - { - return cacheRoot; - } - -} +/** + * The Assets class is used to manage cachable assets. + */ +package ecologylab.io; + +import java.io.File; +import java.net.URLEncoder; + +import ecologylab.appframework.ApplicationEnvironment; +import ecologylab.appframework.ApplicationProperties; +import ecologylab.appframework.Environment; +import ecologylab.appframework.EnvironmentGeneric; +import ecologylab.appframework.PropertiesAndDirectories; +import ecologylab.appframework.SingletonApplicationEnvironment; +import ecologylab.appframework.StatusReporter; +import ecologylab.appframework.types.AssetState; +import ecologylab.appframework.types.AssetsState; +import ecologylab.appframework.types.AssetsTranslations; +import ecologylab.generic.Debug; +import ecologylab.generic.StringBuilderPool; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; + +/** + * Used to manage cachable assets. + *

+ * This class must not be called until codeBase is properly set! + *

+ * Here's how it works: (1) There is a file called assets.xml. It lives only in + * applicationDataDir(), the cache root. There is *no* version of this file in + * /config/preferences, the assets root. + * + * This file stores the *current* cached version # of each asset. + * + * (2) The version of each Asset is a constant, which lives *in the code*. It is passed to + * Assets.downloadZip(). (3) If there is no local versions of assets.xml (first time ap is run), or + * if any version turns out to be stale, the assets.xml file will need to be written to the cache + * root. The application *must* call updateAssetsXml() to do this, after it is finished reading all + * Assets. This method will know if writing the file is needed or not. + * + * @author blake + * @author andruid + */ +public class Assets extends Debug implements ApplicationProperties +{ + /** + * Source URL root of the tree of assets for this application. Default is the configDir(), which + * in turn is the config subdir of codebase. + * + * + * The source location of any asset is specified relative to here. + */ + static ParsedURL assetsRoot; + + protected static final String ASSETS_XML_NAME = "assets.xml"; + + static File assetsXmlFile; + + /** + * Asset version number info! + */ + static AssetsState assetsState; + + static boolean needToWriteAssetsXml; + + /** + * The root directory on the local machine where assets will be stored (cached). + * + * The cache destination of any asset is applied relative to here. + */ + static File cacheRoot; + + /* + * Set-up assets and cache roots. Read currently downloaded + */ + static + { + cacheRoot = /* + * ApplicationEnvironment.runningInEclipse() ? EnvironmentGeneric.configDir().file() + * : + */PropertiesAndDirectories.thisApplicationDir(); + + assetsXmlFile = new File(cacheRoot, ASSETS_XML_NAME); + if (assetsXmlFile.exists()) + { + try + { + assetsState = (AssetsState) AssetsTranslations.get().deserialize(assetsXmlFile, Format.XML); + + } + catch (SIMPLTranslationException e) + { + println("ERROR reading AssetsState from " + assetsXmlFile); + e.printStackTrace(); + } + } + else + { + println("Assets: no cached assets found at " + assetsXmlFile); + } + if (assetsState == null) + assetsState = new AssetsState(); + } + + // //////////////////////////////////////////////////////////// + + /** + * No instances possible, static references only. + */ + private Assets() + { + } + + /** + * Given a relative path, return a file reference to this path from the cache root. + * + * @param relativePath + * A string representing the relative file path. + * @return A file reference to the requested path + */ + public static File getAsset(String relativePath) + { + if (cacheRoot == null) + return null; + + return new File(cacheRoot.getAbsolutePath() + File.separatorChar + relativePath); + } + + /** + * Same as getAsset(String), but allows additional relative file/directory to be specified against + * the relativePath + * + * @param relativePath + * A string representing the relative file path + * @param additionalContext + * A string representing an additional relative path. This path is relative to the + * relativePath parameter (rather than the cache root). + * @return A file reference to the requested path + */ + public static File getAsset(String relativePath, String additionalContext) + { + if (cacheRoot == null) + return null; + + return new File(getAsset(relativePath), additionalContext); + } + + /** + * Same as getAsset(String), but creates the Asset location if it doesn't exist + * + * @param relativePath + * A string representing the relative file path. + * @return A file reference tot he requested path + */ + public static File getAndPerhapsCreateAsset(String relativePath) + { + File theAsset = getAsset(relativePath); + + if (!theAsset.exists()) + theAsset.mkdirs(); + + return theAsset; + } + + /** + * Same as getAndPerhapsCreateAsset(String, String), but creates the Asset location if it doesn't + * exist + * + * @param relativePath + * A string representing the relative file path. + * @param additionalContext + * A string representing an additional relative path. This path is relative to the + * relativePath parameter (rather than the cache root). + * + * @return A file reference to the requested path + * @see #getAsset(String, String) + */ + public static File getAndPerhapsCreateAsset(String relativePath, String additionalContext) + { + File theAsset = getAsset(relativePath, additionalContext); + + if (!theAsset.exists()) + theAsset.mkdirs(); + + return theAsset; + } + + public static File getAsset(AssetsRoot assetsRoot, String relativePath) + { + return Files.newFile(assetsRoot.getCacheRoot(), relativePath); + } + + public static File getAsset(AssetsRoot assetsRoot, String relativePath, String assetName, + StatusReporter status, boolean forceDownload, float version) + { + File result = relativePath != null ? getAsset(assetsRoot, relativePath) + : assetsRoot.getCacheRoot(); + if (!SingletonApplicationEnvironment.runningInEclipse()) + downloadZip(assetsRoot, assetName, status, forceDownload, version); + + return result; + } + + /** + * Version of getAsset that uses a non-singleton ApplicationEnvironment to know where to store + * assets. + * + * @param assetsRoot + * @param relativePath + * @param assetName + * @param status + * @param forceDownload + * @param version + * @param env + * @return + */ + public static File getAsset(AssetsRoot assetsRoot, String relativePath, String assetName, + StatusReporter status, boolean forceDownload, float version, ApplicationEnvironment env) + { + File result = relativePath != null ? getAsset(assetsRoot, relativePath) + : assetsRoot.getCacheRoot(); + if (!env.isRunningInEclipse()) + downloadZip(assetsRoot, assetName, status, forceDownload, version); + + return result; + } + + public static void downloadZip(ParsedURL sourceZip, File targetFile, boolean forceDownload, + float version) + { + downloadZip(sourceZip, targetFile, null, forceDownload, version); + } + + public static void downloadZip(AssetsRoot assetsRoot, String assetName, StatusReporter status, + boolean forceDownload, float version) + { + downloadZip(assetsRoot.getAssetRoot().getRelative(assetName + ".zip", "forming zip location"), + assetsRoot.getCacheRoot(), + status, + forceDownload, + version); + } + + /** + * Download and uncompress a zip file from a source to a target location with minimal effort, + * unless the zip file already exists at the target location, in which case, do nothing. + * + * @param status + * The Status object that provides a source of state change visibility; can be null. + * @param forceDownload + * @param version + */ + public static void downloadZip(ParsedURL sourceZip, File targetDir, StatusReporter status, + boolean forceDownload, float version) + { + String zipFileName = sourceZip.url().getFile(); + int lastSlash = zipFileName.lastIndexOf('\\'); + if (lastSlash == -1) + lastSlash = zipFileName.lastIndexOf('/'); + + zipFileName = zipFileName.substring(lastSlash + 1); + File zipFileDestination = Files.newFile(targetDir, zipFileName); + if (forceDownload || !zipFileDestination.canRead() + || !localVersionIsUpToDate(zipFileName, version)) + { + if (targetDir.exists()) + Files.deleteDirectory(targetDir); + ZipDownload downloadingZip = ZipDownload.downloadAndPerhapsUncompress(sourceZip, + targetDir, + status, + true); + + Debug.println("downloading zip: " + downloadingZip.toString()); + + if (downloadingZip != null) // null if already available locally or error + { + downloadingZip.waitForDownload(); + } + } + else + println("Using cached " + zipFileDestination); + } + + /** + * Get the source URL root of the tree of assets for this application. Default is the configDir(), + * which in turn is the config subdir of codebase. + * + * @return ParsedURL referring to the root of the remote place we download assets from. + */ + public static ParsedURL assetsRoot() + { + return EnvironmentGeneric.configDir(); + } + + /** + * Get the source URL root of the tree of assets for this application. Default is the configDir(), + * which in turn is the config subdir of codebase. + * + * @return ParsedURL referring to the root of the remote place we download assets from. + */ + public static ParsedURL assetsRoot(Environment e) + { + return EnvironmentGeneric.configDir(e); + } + + /** + * Get the root file path for caching. Assets are specified relative to this path. + * + * @return + */ + public static File cacheRoot() + { + return cacheRoot; + } + + /** + * Download XML from the sourcePath, within the assetsRoot (the application's config dir), to the + * target path within the applicationDir. + * + * @param sourcePath + * @param targetPath + * @param status + */ + public static void downloadXML(String sourcePath, String targetPath, StatusReporter status) + { + File targetDir = cacheRoot(); + if ((targetPath != null) && (targetPath.length() > 0)) + targetDir = Files.newFile(targetDir, targetPath); + + downloadXML(assetsRoot().getRelative(sourcePath, "forming Asset path location"), + targetDir, + status); + } + + /** + * Download XML from the sourcePath, within the assetsRoot (the application's config dir), to the + * target path within the applicationDir. + * + * @param sourcePath + * @param targetPath + * @param status + */ + public static void downloadXML(Environment e, String sourcePath, String targetPath, + StatusReporter status) + { + File targetDir = cacheRoot(); + if ((targetPath != null) && (targetPath.length() > 0)) + targetDir = Files.newFile(targetDir, targetPath); + + downloadXML(EnvironmentGeneric.configDir(e).getRelative(sourcePath, + "forming Asset path location"), + targetDir, + status); + } + + /** + * Download an XML file from a source to a target location with minimal effort, unless the XML + * file already exists at the target location, in which case, do nothing. + * + * @param status + * The Status object that provides a source of state change visiblity; can be null. + * @param sourceXML + * The location of the zip file to download and uncompress. + * @param targetDir + * The location where the zip file should be uncompressed. This directory structure will + * be created if it doesn't exist. + */ + public static void downloadXML(ParsedURL sourceXML, File targetDir, StatusReporter status) + { + String xmlFileName = sourceXML.url().getFile(); + int lastSlash = xmlFileName.lastIndexOf('\\'); + if (lastSlash == -1) + lastSlash = xmlFileName.lastIndexOf('/'); + + xmlFileName = xmlFileName.substring(lastSlash + 1); + File xmlFileDestination = Files.newFile(targetDir, xmlFileName); + + if (!xmlFileDestination.canRead()) + { + // we just want to download it, not uncompress it... (using code from zip downloading stuff) + ZipDownload downloadingZip = ZipDownload.downloadAndPerhapsUncompress(sourceXML, + targetDir, + status, + false); + if (downloadingZip != null) // null if already available locally or error + { + downloadingZip.waitForDownload(); + } + } + else + println("Using cached " + xmlFileDestination); + } + + static public final float IGNORE_VERSION = 0f; + + /** + * Determines if a file should be downloaded again, based upon it's file version. + * + * @param id + * the name of the file to check + * @param requiredVersion + * the version of that file \ + * @return false if the local asset is stale and to download true if the local version is fine and + * we dont need to download + */ + public static boolean localVersionIsUpToDate(String id, float requiredVersion) + { + if (requiredVersion == IGNORE_VERSION) + return true; + + AssetState assetState = assetsState.lookup(id); + boolean result = assetState != null; + if (result) + { + float localVersion = assetState.getVersion(); + result = requiredVersion <= localVersion; + } + else + { // create an entry to write later when the application developer calls updateAssetsXml(). + assetState = assetsState.update(id); + } + if (!result) + { + needToWriteAssetsXml = true; + assetState.setVersion(requiredVersion); // update the version in our data structure + } + + return result; + } + + /** + * When necessary, re-write the local (and only) assets.xml file. + * + */ + public static void updateAssetsXml(String sourceSpot) + { + try + { + sourceSpot = " from " + sourceSpot; + if (needToWriteAssetsXml) + { + needToWriteAssetsXml = false; + // assetsState.translateToXML(assetsXmlFile); + + SimplTypesScope.serialize(assetsState, assetsXmlFile, Format.XML); + + println("Saved Assets XML" + sourceSpot + ": " + assetsXmlFile); + } + else + println("NO NEED to Save Assets XML" + sourceSpot + ": " + assetsXmlFile); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + } + + private static final StringBuilderPool stringPool = new StringBuilderPool(2, 255); + + /** + * Derive a non-duplicate cache filename given a ParsedURL location + * + * @param location + * The location of the file to be cached. + * @param directory + * The directory to cache the file + * @param additional + * An additional text to add to the end of the filename, but before the extension + * @param separator + * Separator used to divide sections of filename (e.g. "-", ".") + * @param extension + * Extension to add to file name if it doesn't already exist + * + * @return A string containing the new filename + */ + @SuppressWarnings("deprecation") + public static String getCacheFilename(ParsedURL location, File directory, String additional, + String separator, String extension) + { + StringBuilder filename = stringPool.nextBuffer(); + filename.append(location.host()); + filename.append(separator); + String locationString = location.url().getPath(); + String query = location.url().getQuery(); + filename.append(locationString.substring(locationString.lastIndexOf('/') + 1)); + if (query != null && query.length() > 0) + { + filename.append("%3F"); + filename.append(URLEncoder.encode(query)); + } + + if (additional != null) + { + filename.append(separator); + filename.append(additional); + } + + if (extension != null && !locationString.endsWith(extension)) + { + filename.append("."); + filename.append(extension); + } + + String filenameString = filename.toString(); + // File localFile = new File(directory, filename.toString()); + // if (localFile.exists()) + // { + // int extensionStart = filename.lastIndexOf("."); + // int count = 1; + // String pre = filename.substring(0, extensionStart); + // String end = filename.substring(extensionStart); + // + // while(localFile.exists()) + // { + // StringBuilder newFilename = stringPool.nextBuffer(); + // newFilename.append(pre); + // newFilename.append(separator); + // newFilename.append(count); + // newFilename.append(end); + // filenameString = newFilename.toString(); + // localFile = new File(directory, filenameString); + // count++; + // stringPool.release(newFilename); + // } + // stringPool.release(filename); + // } + + return filenameString; + } + + /** + * @return the assetsRoot + */ + public static ParsedURL getAssetsRoot() + { + return assetsRoot; + } + + /** + * @return the cacheRoot + */ + public static File getCacheRoot() + { + return cacheRoot; + } + +} diff --git a/simplCore/src/ecologylab/io/ByteBufferPool.java b/simplCore/src/ecologylab/io/ByteBufferPool.java index f21e0963..306d3101 100644 --- a/simplCore/src/ecologylab/io/ByteBufferPool.java +++ b/simplCore/src/ecologylab/io/ByteBufferPool.java @@ -1,112 +1,112 @@ -/* - * Created on Nov 19, 2007 - */ -package ecologylab.io; - -import java.nio.ByteBuffer; -import java.util.ArrayList; - -import ecologylab.generic.Debug; -import ecologylab.generic.ResourcePoolWithSize; - -/** - * This class maintains a collection of ByteBuffers, which may be acquir()'ed for temporary use. - * - * @author Zach Toups (toupsz@gmail.com) - */ -public class ByteBufferPool extends ResourcePoolWithSize -{ - /** - * Instantiates a new, empty ByteBufferPool. - * - * @param maxBufferSize - - * specifies the size of the (immutable) ByteBuffers that will be created within this pool. - */ - public ByteBufferPool(int poolSize, int minimumCapacity, int maxBufferSize) - { - super(poolSize, minimumCapacity, maxBufferSize); - } - - /** - * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) - */ - @Override protected void clean(ByteBuffer objectToClean) - { - // clear is fast a cheap, just adjusts the mark, capacity, and position - objectToClean.clear(); - } - - /** - * @see ecologylab.generic.ResourcePool#generateNewResource() - */ - @Override protected ByteBuffer generateNewResource() - { - return ByteBuffer.allocate(this.resourceObjectCapacity); - } - - public static void main(String[] args) - { - Debug.println("make a pool of 3"); - ByteBufferPool p = new ByteBufferPool(9, 3, 100); - - ArrayList b = new ArrayList(8); - - Debug.println("acquire 100 times"); - for (int i = 0; i < 100; i++) - { - b.add(p.acquire()); - } - - Debug.println("release 100 times"); - for (int i = 0; i < 100; i++) - { - p.release(b.remove(b.size()-1)); - } - - Debug.println("test release function"); - - ByteBuffer bb = p.acquire(); - - Debug.println("bb: "+bb); - - bb = p.release(bb); - - Debug.println("bb: "+bb); - - Debug.println("acquire 100 times"); - for (int i = 0; i < 100; i++) - { - b.add(p.acquire()); - } - - Debug.println("acquire 100 times"); - for (int i = 0; i < 100; i++) - { - b.add(p.acquire()); - } - - Debug.println("acquire 100 times"); - for (int i = 0; i < 100; i++) - { - b.add(p.acquire()); - } - - Debug.println("release 100 times"); - for (int i = 0; i < 100; i++) - { - p.release(b.remove(b.size()-1)); - } - - Debug.println("release 100 times"); - for (int i = 0; i < 100; i++) - { - p.release(b.remove(b.size()-1)); - } - - Debug.println("release 100 times"); - for (int i = 0; i < 100; i++) - { - p.release(b.remove(b.size()-1)); - } - } -} +/* + * Created on Nov 19, 2007 + */ +package ecologylab.io; + +import java.nio.ByteBuffer; +import java.util.ArrayList; + +import ecologylab.generic.Debug; +import ecologylab.generic.ResourcePoolWithSize; + +/** + * This class maintains a collection of ByteBuffers, which may be acquir()'ed for temporary use. + * + * @author Zach Toups (toupsz@gmail.com) + */ +public class ByteBufferPool extends ResourcePoolWithSize +{ + /** + * Instantiates a new, empty ByteBufferPool. + * + * @param maxBufferSize - + * specifies the size of the (immutable) ByteBuffers that will be created within this pool. + */ + public ByteBufferPool(int poolSize, int minimumCapacity, int maxBufferSize) + { + super(poolSize, minimumCapacity, maxBufferSize); + } + + /** + * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) + */ + @Override protected void clean(ByteBuffer objectToClean) + { + // clear is fast a cheap, just adjusts the mark, capacity, and position + objectToClean.clear(); + } + + /** + * @see ecologylab.generic.ResourcePool#generateNewResource() + */ + @Override protected ByteBuffer generateNewResource() + { + return ByteBuffer.allocate(this.resourceObjectCapacity); + } + + public static void main(String[] args) + { + Debug.println("make a pool of 3"); + ByteBufferPool p = new ByteBufferPool(9, 3, 100); + + ArrayList b = new ArrayList(8); + + Debug.println("acquire 100 times"); + for (int i = 0; i < 100; i++) + { + b.add(p.acquire()); + } + + Debug.println("release 100 times"); + for (int i = 0; i < 100; i++) + { + p.release(b.remove(b.size()-1)); + } + + Debug.println("test release function"); + + ByteBuffer bb = p.acquire(); + + Debug.println("bb: "+bb); + + bb = p.release(bb); + + Debug.println("bb: "+bb); + + Debug.println("acquire 100 times"); + for (int i = 0; i < 100; i++) + { + b.add(p.acquire()); + } + + Debug.println("acquire 100 times"); + for (int i = 0; i < 100; i++) + { + b.add(p.acquire()); + } + + Debug.println("acquire 100 times"); + for (int i = 0; i < 100; i++) + { + b.add(p.acquire()); + } + + Debug.println("release 100 times"); + for (int i = 0; i < 100; i++) + { + p.release(b.remove(b.size()-1)); + } + + Debug.println("release 100 times"); + for (int i = 0; i < 100; i++) + { + p.release(b.remove(b.size()-1)); + } + + Debug.println("release 100 times"); + for (int i = 0; i < 100; i++) + { + p.release(b.remove(b.size()-1)); + } + } +} diff --git a/simplCore/src/ecologylab/io/DownloadProcessor.java b/simplCore/src/ecologylab/io/DownloadProcessor.java index b7466333..27da6a70 100644 --- a/simplCore/src/ecologylab/io/DownloadProcessor.java +++ b/simplCore/src/ecologylab/io/DownloadProcessor.java @@ -1,30 +1,30 @@ -package ecologylab.io; - -import java.io.IOException; - -import ecologylab.concurrent.Downloadable; -import ecologylab.generic.Continuation; - - -/** - * Interface to a module that performs downloads, perhaps concurrently. - * A wrapper for DownloadMonitor, for example. - * - * @author andruid - */ -public interface DownloadProcessor -{ - public void stop(); - -/** - * Download the Downloadable, perhaps concurrently. - * If concurrently, call the Continuation.callback(T) method when done. - * - * @param thatDownloadable - * @param dispatchTarget - * @throws IOException - */ - public void download(T thatDownloadable, Continuation continuation); - - public void requestStop(); -} +package ecologylab.io; + +import java.io.IOException; + +import ecologylab.concurrent.Downloadable; +import ecologylab.generic.Continuation; + + +/** + * Interface to a module that performs downloads, perhaps concurrently. + * A wrapper for DownloadMonitor, for example. + * + * @author andruid + */ +public interface DownloadProcessor +{ + public void stop(); + +/** + * Download the Downloadable, perhaps concurrently. + * If concurrently, call the Continuation.callback(T) method when done. + * + * @param thatDownloadable + * @param dispatchTarget + * @throws IOException + */ + public void download(T thatDownloadable, Continuation continuation); + + public void requestStop(); +} diff --git a/simplCore/src/ecologylab/io/DownloadableFileToDisk.java b/simplCore/src/ecologylab/io/DownloadableFileToDisk.java index 4d53d10c..0937c8ff 100644 --- a/simplCore/src/ecologylab/io/DownloadableFileToDisk.java +++ b/simplCore/src/ecologylab/io/DownloadableFileToDisk.java @@ -1,235 +1,235 @@ -package ecologylab.io; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import ecologylab.appframework.StatusReporter; -import ecologylab.concurrent.BasicSite; -import ecologylab.concurrent.Downloadable; -import ecologylab.concurrent.DownloadableLogRecord; -import ecologylab.generic.Continuation; -import ecologylab.generic.Debug; -import ecologylab.net.ParsedURL; - -public class DownloadableFileToDisk -extends Debug -implements Downloadable, Continuation -{ - private boolean downloadDone = false; - private boolean downloadStarted = false; - - private InputStream inputStream = null; - - private OutputStream outputStream; - - private ParsedURL target; - private File destination; - - private static final int BUFFER_SIZE = 8192; - private StatusReporter status = null; - private int fileSize = -1; - - public DownloadableFileToDisk(ParsedURL target, File destination, StatusReporter status) - { - this.target = target; - this.destination = destination; - this.status = status; - } - - public DownloadableFileToDisk(ParsedURL target, InputStream inputStream, File destination, StatusReporter status) - { - this(target, destination, status); - this.inputStream = inputStream; - } - - public DownloadableFileToDisk(ParsedURL target, File destination) - { - this(target, destination, null); - } - - public DownloadableFileToDisk(ParsedURL target, InputStream inputStream, File destination) - { - this(target, inputStream, destination, null); - } - - @Override - public void handleIoError(Throwable e) - { - closeStreams(); - downloadDone = true; - } - - public boolean isDownloadDone() - { - return downloadDone; - } - - @Override - public void performDownload() throws IOException - { - debug("performDownload() top"); - if (downloadStarted) - return; - - downloadStarted = true; - - //this gets the stream and sets the member field 'fileSize' - // inputStream = getInputStream(zipSource); - if (inputStream == null) - inputStream = target.url().openStream(); - - debug("performDownload() got InputStream"); - - //actually read and write the file - // if the file already exists, delete it - //FIXME -- consider using the existing, instead of deleting it!!! - if (destination.exists()) - { - boolean deleted = destination.delete(); - debug("File exists, so deleting = " + deleted); - } - - outputStream = new BufferedOutputStream(new FileOutputStream(destination)); - debug("performDownload() got outputStream from " + destination); - - byte fileBytes[] = new byte[BUFFER_SIZE]; - - //Read data from the source url and write it out to the file - int count = 0; - int lastTenth = 1; - int incrementSize = fileSize/10; - //int i=0; - while(( count = inputStream.read(fileBytes, 0, BUFFER_SIZE)) != -1 ) - { - if (status != null) - { - //Our status will be in 10% increments - if (count >= incrementSize*(lastTenth)) - status.display("Downloading file " + destination.getName(), - 1, count/10, incrementSize); - - //can't just increment because we maybe skip/hit 1/10ths due to - //faster/slower transfer rates, traffic, etc. - lastTenth = (int) Math.floor(((double)count/fileSize)*10); - } - outputStream.write(fileBytes, 0, count); - } - - closeStreams(); - - synchronized (this) - { - downloadDone = true; - } - } - - public void closeStreams() - { - try - { - if (outputStream != null) - { - OutputStream oStream = this.outputStream; - this.outputStream = null; - oStream.close(); - } - } catch (IOException e) - { - e.printStackTrace(); - } - - try - { - if (inputStream != null) - { - InputStream iStream = this.inputStream; - this.inputStream = null; - iStream.close(); - } - } catch (IOException e) - { - e.printStackTrace(); - } - } - - @Override - public void callback(Object o) - { - System.out.println("Finished download file: " + target + " -> " + destination); - } - - @Override - public boolean isRecycled() - { - // TODO Auto-generated method stub - return false; - } - - @Override - public BasicSite getSite() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public ParsedURL location() - { - return target; - } - /** - * - * @return What to tell the user about what is being downloaded. - */ - @Override - public String message() - { - return null; - } - - @Override - public void recycle() - { - } - - /** - * Default empty implementation; will be ignored for this type. - */ - @Override - public boolean isImage() - { - return false; - } - - @Override - public BasicSite getDownloadSite() - { - return null; - } - - @Override - public ParsedURL getDownloadLocation() - { - // TODO Auto-generated method stub - return location(); - } - - @Override - public boolean isCached() - { - // TODO Auto-generated method stub - return false; - } - - @Override - public DownloadableLogRecord getLogRecord() - { - // TODO Auto-generated method stub - return null; - } - -} +package ecologylab.io; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import ecologylab.appframework.StatusReporter; +import ecologylab.concurrent.Downloadable; +import ecologylab.concurrent.DownloadableLogRecord; +import ecologylab.concurrent.Site; +import ecologylab.generic.Continuation; +import ecologylab.generic.Debug; +import ecologylab.net.ParsedURL; + +public class DownloadableFileToDisk +extends Debug +implements Downloadable, Continuation +{ + private boolean downloadDone = false; + private boolean downloadStarted = false; + + private InputStream inputStream = null; + + private OutputStream outputStream; + + private ParsedURL target; + private File destination; + + private static final int BUFFER_SIZE = 8192; + private StatusReporter status = null; + private int fileSize = -1; + + public DownloadableFileToDisk(ParsedURL target, File destination, StatusReporter status) + { + this.target = target; + this.destination = destination; + this.status = status; + } + + public DownloadableFileToDisk(ParsedURL target, InputStream inputStream, File destination, StatusReporter status) + { + this(target, destination, status); + this.inputStream = inputStream; + } + + public DownloadableFileToDisk(ParsedURL target, File destination) + { + this(target, destination, null); + } + + public DownloadableFileToDisk(ParsedURL target, InputStream inputStream, File destination) + { + this(target, inputStream, destination, null); + } + + @Override + public void handleIoError(Throwable e) + { + closeStreams(); + downloadDone = true; + } + + public boolean isDownloadDone() + { + return downloadDone; + } + + @Override + public void performDownload() throws IOException + { + debug("performDownload() top"); + if (downloadStarted) + return; + + downloadStarted = true; + + //this gets the stream and sets the member field 'fileSize' + // inputStream = getInputStream(zipSource); + if (inputStream == null) + inputStream = target.url().openStream(); + + debug("performDownload() got InputStream"); + + //actually read and write the file + // if the file already exists, delete it + //FIXME -- consider using the existing, instead of deleting it!!! + if (destination.exists()) + { + boolean deleted = destination.delete(); + debug("File exists, so deleting = " + deleted); + } + + outputStream = new BufferedOutputStream(new FileOutputStream(destination)); + debug("performDownload() got outputStream from " + destination); + + byte fileBytes[] = new byte[BUFFER_SIZE]; + + //Read data from the source url and write it out to the file + int count = 0; + int lastTenth = 1; + int incrementSize = fileSize/10; + //int i=0; + while(( count = inputStream.read(fileBytes, 0, BUFFER_SIZE)) != -1 ) + { + if (status != null) + { + //Our status will be in 10% increments + if (count >= incrementSize*(lastTenth)) + status.display("Downloading file " + destination.getName(), + 1, count/10, incrementSize); + + //can't just increment because we maybe skip/hit 1/10ths due to + //faster/slower transfer rates, traffic, etc. + lastTenth = (int) Math.floor(((double)count/fileSize)*10); + } + outputStream.write(fileBytes, 0, count); + } + + closeStreams(); + + synchronized (this) + { + downloadDone = true; + } + } + + public void closeStreams() + { + try + { + if (outputStream != null) + { + OutputStream oStream = this.outputStream; + this.outputStream = null; + oStream.close(); + } + } catch (IOException e) + { + e.printStackTrace(); + } + + try + { + if (inputStream != null) + { + InputStream iStream = this.inputStream; + this.inputStream = null; + iStream.close(); + } + } catch (IOException e) + { + e.printStackTrace(); + } + } + + @Override + public void callback(Object o) + { + System.out.println("Finished download file: " + target + " -> " + destination); + } + + @Override + public boolean isRecycled() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public Site getSite() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public ParsedURL location() + { + return target; + } + /** + * + * @return What to tell the user about what is being downloaded. + */ + @Override + public String message() + { + return null; + } + + @Override + public void recycle() + { + } + + /** + * Default empty implementation; will be ignored for this type. + */ + @Override + public boolean isImage() + { + return false; + } + + @Override + public Site getDownloadSite() + { + return null; + } + + @Override + public ParsedURL getDownloadLocation() + { + // TODO Auto-generated method stub + return location(); + } + + @Override + public boolean isCached() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public DownloadableLogRecord getLogRecord() + { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/simplCore/src/ecologylab/io/Files.java b/simplCore/src/ecologylab/io/Files.java index caba47f4..a1459774 100644 --- a/simplCore/src/ecologylab/io/Files.java +++ b/simplCore/src/ecologylab/io/Files.java @@ -1,1080 +1,1080 @@ -package ecologylab.io; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -import java.net.URLConnection; -import java.nio.channels.FileChannel; -import java.util.Date; - -import ecologylab.generic.Debug; -import ecologylab.generic.StringTools; - -/** - * A set of lovely convenience methods for doing operations on local files. - */ -public class Files extends Debug -{ - // to update, add entry here, and below in deriveLang() - public static final int NONE = -1; - - public static final int UNKNOWN = -1024; - - public static final int HTML = 0; - - public static final int JAVA = 1; - - public static final int JAVASCRIPT = 2; - - public static final int ASP = 3; - - public static final int CSS = 4; - - public static final int EXE = 5; - - public File outFile, inFile; - - public BufferedReader fileReader; - - public BufferedWriter fileWriter; - - String tempFileName; - - static String readErrorString = "Error reading from file "; - - static String writeErrorString = "Error writing to file "; - - public static final char sep = File.separatorChar; - - static public final String indent = "\t"; - - public Files() - { - } - - public Files(String inFileName) - { - setInFile(inFileName); - } - - public void setInFile(String inFileName) - { - inFile = newFile(inFileName); - } - - /** - * Create a new File object. - * - * More robust than just calling the File constructor, cause it converts all slashes to the - * direction native for the platform. - */ - public static File newFile(String inFileName) - { - return newFile((File) null, inFileName); - } - - /** - * Create a new File object. - * - * More robust than just calling the File constructor, cause it converts all slashes to the - * direction native for the platform. - */ - public static File newFile(String contextName, String inFileName) - { - return newFile(newFile(contextName), inFileName); - } - - /** - * Create a new File object. - * - * More robust than just calling the File constructor, cause it converts all slashes to the - * direction native for the platform. - */ - public static File newFile(File context, String inFileName) - { - // one of the replaces should do something; - // and the other should do nothing. - String fixedFileName = inFileName.replace('/', sep).replace('\\', sep); - File one = new File(fixedFileName); - if (context == null) - return one; - if (one.isAbsolute() || (context == null)) - { - // hack gnarly windows path shit - // (drives & backslashes are a plague on all programmers) - if (fixedFileName.length() > 1 && fixedFileName.charAt(1) != ':') - { - String contextName = context.getPath(); - if (contextName.charAt(1) == ':') - { - String fixedFixed = contextName.substring(0, 2) + fixedFileName; - return new File(fixedFixed); - } - } - return one; - } - // else - // Debug.println("newFile: (0)="+fixedFileName.charAt(0) + " (1)"+ - // fixedFileName.charAt(0)); - // if ((fixedFileName.charAt(1) == ':') || (fixedFileName.charAt(0) == sep)) - // return new File(fixedFileName); - // else - return new File(context, fixedFileName); - } - - public void close() - { - closeReader(); - closeWriter(); - } - - public boolean closeReader() - { - return closeReader(fileReader); - } - - public static boolean closeReader(BufferedReader reader) - { - boolean ok = true; - if (reader != null) - try - { - reader.close(); - } - catch (IOException ioe) - { - ok = false; - } - return ok; - } - - public boolean closeWriter() - { - return closeWriter(fileWriter); - } - - public static boolean closeWriter(BufferedWriter writer) - { - boolean ok = true; - try - { - writer.close(); - } - catch (IOException outE) - { - ok = false; - } - return ok; - } - - public static BufferedReader openReader(String fileName) - { - return openReader(newFile(fileName)); - } - - // public static BufferedReader openWebReader(String webAddr) - // { - // /* get ParsedURL from url string. */ - // ParsedURL purl = EnvironmentGeneric.getRelativeOrAbsolute(webAddr, ""); - // return openReader(purl.url()); - // } - - public static BufferedReader openReader(File file) - { - boolean ok = file.canRead(); - if (!ok) - { - println("Can't read file " + file.getAbsolutePath()); - return null; - } - println(3, "Input file: " + file); - FileReader fileReader = null; - try - { - fileReader = new FileReader(file); - return openReader(fileReader); - } - catch (FileNotFoundException e) - { - println("Can't find file " + file.getAbsolutePath()); - return null; - } - } - - public static InputStream openStream(URL url) - { - InputStream inStream = null; - try - { - URLConnection connection = url.openConnection(); - inStream = connection.getInputStream(); - } - catch (FileNotFoundException e) - { - println("Can't open because FileNotFoundException: " + url); - } - catch (IOException e) - { - println("Can't open because IOException: " + url); - } - catch (Exception e) // catch all exceptions, including security - { - println("Can't open " + url); - e.printStackTrace(); - } - return inStream; - } - - public static BufferedReader openReader(URL url) - { - InputStream inStream = openStream(url); - return (inStream == null) ? null : openReader(inStream); - } - - public static BufferedReader openReader(InputStream inStream) - { - return openReader(new InputStreamReader(inStream)); - } - - public static BufferedReader openReader(InputStreamReader inputStreamReader) - { - return new BufferedReader(inputStreamReader); - } - - public boolean openRead(File inputFile) - { - inFile = inputFile; - return openReader(); - } - - public boolean openRead(String inFileName) - { - setInFile(inFileName); - return openReader(); - } - - public static String getTempFileName(String name) - { - Date myZone = new Date(); - return sep + "temp" + sep + name + myZone.getTime(); - } - - public boolean openReader() - { - fileReader = openReader(inFile); - return (fileReader != null); - } - - public String getDir(String fullPath) - { - int index = fullPath.lastIndexOf(File.separator); - if (index == -1) - return ""; - return fullPath.substring(0, index); - } - - public boolean openWrite(String outFileName) - { - return openWrite(newFile(outFileName)); - } - - public boolean openWrite(File outDir, String outFileName) - { - return openWrite(newFile(outDir, outFileName)); - } - - public boolean openWrite(File oFile) - { - outFile = oFile; - BufferedWriter writer = openWriter(oFile); - boolean ok = (writer != null); - if (ok) - fileWriter = writer; - return ok; - } - - public static BufferedWriter openWriter(String oFileName) - { - return openWriter(newFile(oFileName)); - } - - public static BufferedWriter openWriter(String oFileName, boolean append) - { - return openWriter(newFile(oFileName), 1, append); - } - - public static BufferedWriter openWriter(File oFile, boolean append) - { - return openWriter(oFile, 1, append); - } - - public static BufferedWriter openWriter(File oFile) - { - return openWriter(oFile, 1); - } - - /** - * Make any directories necesary for the file to be written. - */ - public static boolean makePath(File oFile) - { - String oFileDirName = oFile.getParent(); - File oFileDir = newFile(oFileDirName); - boolean result = !oFileDir.equals(""); - if (result) // if ok, continue - { - result = oFileDir.exists(); - if (!result) // if exists, no more work to do - { - println("\t"); - println(oFileDir + " "); - result = oFileDir.mkdirs(); - if (!result) - Debug.println("[Making directories for you: failed.]"); - } - } - else - Debug.println("Can't write to " + oFile.getAbsolutePath()); - return result; - } - - public static BufferedWriter openWriter(File oFile, int debugLevel) - { - if (oFile == null) - return null; - - BufferedWriter writer = null; - - String oFileFullPath = oFile.getAbsolutePath(); - - println("Files.openWriter(" + oFileFullPath); - - // if (makePath(oFile)) // maybe create directories along the path - try - { - writer = new BufferedWriter(new FileWriter(oFile)); - println("\tOutput file: "); - println(indent + indent + oFileFullPath); - } - catch (IOException e) - { - Debug.println(writeErrorMsg(e, oFileFullPath)); - } - return writer; - } - - public static BufferedWriter openWriter(File oFile, int debugLevel, boolean append) - { - if (oFile == null) - return null; - BufferedWriter writer = null; - - String oFileFullPath = oFile.getAbsolutePath(); - - println("Files.openWriter(" + oFileFullPath); - - // if (makePath(oFile)) // maybe create directories along the path - try - { - writer = new BufferedWriter(new FileWriter(oFile, append)); - println("\tOutput file: "); - println(indent + indent + oFileFullPath); - } - catch (IOException e) - { - Debug.println(writeErrorMsg(e, oFileFullPath)); - } - return writer; - } - - public static FileInputStream openInStream(File inFile) - { - FileInputStream stream = null; - try - { - stream = new FileInputStream(inFile); - } - catch (Exception e) - { - Debug.println("Can't open input stream from " + inFile + " " + e); - } - return stream; - } - - public static BufferedOutputStream openOutStream(File oFile) - { - BufferedOutputStream outStream = null; - - String oFileFullPath = oFile.getAbsolutePath(); - - if (makePath(oFile)) // maybe create directories along the path - try - { - outStream = new BufferedOutputStream(new FileOutputStream(oFile)); - println(3, "Output file: "); - println(3, indent + oFileFullPath); - } - catch (IOException e) - { - Debug.println(writeErrorMsg(e, oFileFullPath)); - } - return outStream; - } - - public String readLine() - { - return readLine(fileReader); - } - - public static String readLine(BufferedReader reader) - { - String aLine = " "; - try - { - aLine = reader.readLine(); - } - catch (IOException e) - { - Debug.println(readErrorString + reader); - } - return aLine; - } - - public boolean write(String toWrite) - { - return write(fileWriter, toWrite); - } - - public static boolean write(BufferedWriter writer, String toWrite) - { - if ((toWrite == null) || (toWrite.equals(""))) - return true; - boolean ok = true; - try - { - writer.write(toWrite); - } - catch (IOException e) - { - ok = false; - Debug.println(writeErrorMsg(e, writer)); - } - return ok; - } - - // write a line of output - public boolean writeLine(String toWrite) - { - // Env.println("really writing a line"); - return writeLine(fileWriter, toWrite); - } - - public static boolean writeLine(BufferedWriter writer, String... toWrite) - { - if (toWrite == null) - return true; - boolean ok = true; - try - { - for (String sToWrite : toWrite) - writer.write(sToWrite); - writer.newLine(); - } - catch (IOException e) - { - ok = false; - // dont use Debug, to avoid infinite loops!!! - System.err.println(writeErrorMsg(e, writer)); - } - return ok; - } - - public static boolean flush(BufferedWriter writer) - { - boolean result = false; - try - { - writer.flush(); - result = true; - } - catch (IOException e) - { - - } - return result; - } - - public void rename(String finalName) - { - File newFile = newFile(finalName); - outFile.renameTo(newFile); - // Env.println("All done!!!!!"); - } - - public boolean insertFile(String fileToInsert) - { - return insertFile(fileWriter, fileToInsert); - } - - // TODO this is also old dead code - public static void copyTraceFile(File outputFile) - { - final String TRACE_PATH = System.getProperty("deployment.user.logdir") + "/plugin" - + StringTools.remove(System.getProperty("java.version"), '_') + ".trace"; - BufferedWriter writer; - BufferedReader reader; - reader = openReader(TRACE_PATH); - writer = openWriter(outputFile); - - String oneLine = readLine(reader); - - while (oneLine != null) - { - writeLine(writer, oneLine); - oneLine = readLine(reader); - } - closeReader(reader); - closeWriter(writer); - } - - public static boolean insertFile(BufferedWriter writer, String fileToInsert) - { - BufferedReader reader = openReader(fileToInsert); - boolean ok = (reader != null); - if (ok) - { - String line; - for (line = readLine(reader); line != null; line = readLine(reader)) - { - // Env.println("into " + reader + " inserting: " + line); - writeLine(writer, line); - } - } - try - { - reader.close(); - } - catch (IOException e) - { - ok = false; - } - return ok; - } - - public static boolean isDir(File file) - { - if (file.isDirectory()) - return true; - // this is a bit of a hack -- it assumes files w suffixes - String lastPart = file.getName(); - return lastPart.indexOf(".") < 0; - } - - // ????? i dunno where this was being used (CMDOC???) - // write a line of output - // public boolean writeLine(String toWrite) - // { - // return writeLine(toWrite, false); - // } - public static boolean copy(File from, File to) - { - if (!from.exists()) - { - println("I can't copy because
\n" + from.toString() + " doesn't exist."); - println(""); - return false; - } - println(2, "Copy:"); - println(2, indent + from); - println(2, indent + to); - - File dir; - if (isDir(to)) - { - dir = to; - to = newFile(to, from.getName()); - } - else - dir = newFile(to.getParent()); - - if (!dir.exists()) - dir.mkdirs(); - BufferedReader input = null; - BufferedWriter output = null; - boolean ok = true; - try - { - if (to.exists()) - to.delete(); - input = new BufferedReader(new FileReader(from)); - output = new BufferedWriter(new FileWriter(to)); - // output = new FileOutputStream(to); - } - catch (IOException e) - { - Debug.println("Files.copy error opening streams: " + e); - ok = false; - } - if (ok) - { - char buf[] = new char[32768]; // 32 K - int count = 0; - try - { - ok = false; - - while ((count = input.read(buf)) >= 0) - { - output.write(buf, 0, count); - } - ok = true; - } - catch (IOException e) - { - File errorFile = ok ? to : from; - String operation = ok ? "writing" : "reading"; - Debug.println("I/O error during copying, while " + operation + " " - + errorFile.getAbsolutePath()); - ok = false; - } - try - { - ok = false; - input.close(); - ok = true; - output.close(); - } - catch (IOException e) - { - File errorFile = ok ? to : from; - Debug.println("I/O error during copying, while closing " + errorFile.getAbsolutePath()); - ok = false; - } - } - return ok; - } - - public static String relativePath(File parent, File child) - { - String parentPath = parent.getAbsolutePath(); - String childPath = child.getAbsolutePath(); - return relativePath(parentPath, childPath); - } - - public static String relativePath(File parent, String childPath) - { - String parentPath = parent.getAbsolutePath(); - return relativePath(parentPath, childPath); - } - - public static String relativePath(String parentPath, String childPath) - { - println(3, "Relative Path:"); - println(3, indent + parentPath); - println(3, indent + childPath); - if (parentPath.equals(childPath)) - return ""; - if (childPath.indexOf(parentPath) > -1) - { - println(3, indent + childPath.substring(parentPath.length() + 1)); - return childPath.substring(parentPath.length() + 1); - } - else - return null; - } - - public static String getBeforeExtension(File file) - { - return getBeforeExtension(file.getName()); - } - - public static String getBeforeExtension(String fName) - { - String before = ""; - int dot = fName.lastIndexOf("."); - if (dot >= 0) - before = fName.substring(0, dot); - return before; - } - - public static String getExtension(File file) - { - return getExtension(file.getName()); - } - - public static String getExtension(String fName) - { - String ext = null; - int dot = fName.lastIndexOf("."); - if ((dot >= 0) && (dot < fName.length() - 1)) - ext = fName.substring(dot + 1); - return ext; - } - - public static int deriveLang(String fName) - { - int lang; - String ext = getExtension(fName); - println(4, "deriveLang got extension='" + ext + "'"); - if (ext == null) - lang = HTML; - { - ext = ext.toLowerCase(); - if (ext.equals("html") || ext.equals("htm")) - lang = HTML; - else if (ext.equals("java")) - lang = JAVA; - else if (ext.equals("js")) - lang = JAVASCRIPT; - else if (ext.equals("asp")) - lang = ASP; - else if (ext.equals("css")) - lang = CSS; - else if (ext.equals("exe")) - lang = EXE; - else - lang = UNKNOWN; - } - return lang; - } - - public static String unix(File f) - { - return f.getAbsolutePath().replace(sep, '/'); - } - - public static String unix(String s) - { - return s.replace(sep, '/'); - } - - public static boolean contains(String fileName, String s) - { - return contains(fileName, s); - } - - public static boolean contains(File f, String s) - { - BufferedReader reader = openReader(f); - for (String line = Files.readLine(reader); line != null; line = Files.readLine(reader)) - { - if (line.indexOf(s) > -1) - return true; - } - return false; - } - - public static File removeExtension(File f) - { - return (f.getName().indexOf('.') == -1) ? f : removeExtension(f.getPath()); - } - - public static File removeExtension(String path) - { - File result; - int lastDot = path.lastIndexOf('.'); - int lastSlash = path.lastIndexOf(sep); - if (lastDot > lastSlash) - { - path = path.substring(0, lastDot); - result = new File(path); - } - else - result = new File(path); - return result; - } - - // public static void main(String[] s) - // { - // // println(removeExtension(new File("c:/temp/foo.xml")).toString()); - // BufferedReader reader = openWebReader(s[0]); - // String thatLine = null; - // while ((thatLine = Files.readLine(reader)) != null) - // { - // println("read from URL " + thatLine); - // } - // closeReader(reader); - // } - - public static void main2(String[] args) throws Exception - { - URL yahoo = new URL("http://www.yahoo.com/"); - BufferedReader in = new BufferedReader(new InputStreamReader(yahoo.openStream())); - - String inputLine; - - while ((inputLine = in.readLine()) != null) - System.out.println(inputLine); - - in.close(); - } - - public static String writeErrorMsg(Throwable e, Object o) - { - return writeErrorMsg(e, o.toString()); - } - - public static String writeErrorMsg(Throwable e, File f) - { - return writeErrorMsg(e, f.getAbsolutePath()); - } - - public static String writeErrorMsg(Throwable e, String path) - { - return "Error [" + e.getMessage() + "] writing to file " + path; - } - - /** - * removes all the files in a given directory - * - * @param dir - * the dir to be cleared - */ - public static void clearDir(File dir) - { - if (dir.isDirectory()) - { - String[] children = dir.list(); - for (int i = 0; i < children.length; i++) - { - new File(dir, children[i]).delete(); - } - } - } - - /** - * copies all the files of a particular type from the src dir to the dest dir - * - * @param srcDir - * source dir - * @param dstDir - * destination dir - * @param fileType - * type of the file, for example jpg for jpeg files if fileType is null, all the files - * are copied - */ - public static void copyFiles(File srcDir, File dstDir, String fileType) - { - if (srcDir.isDirectory()) - { - String[] children = srcDir.list(); - for (int i = 0; i < children.length; i++) - { - if (fileType != null) - { - // copy only if the file is of the specified type - if (children[i].endsWith(fileType)) - copyFile(new File(srcDir, children[i]), new File(dstDir, children[i])); - } - else - { - copyFile(new File(srcDir, children[i]), new File(dstDir, children[i])); - } - } - } - } - - /** - * Copy a file -- binary or character data. - * - * @param srcFile - * @param dstFile - */ - public static void copyFile(File srcFile, File dstFile) - { - try - { - // Create channel on the source - FileChannel srcChannel = new FileInputStream(srcFile).getChannel(); - - // Create channel on the destination - FileChannel dstChannel = new FileOutputStream(dstFile).getChannel(); - - // Copy file contents from source to destination - dstChannel.transferFrom(srcChannel, 0, srcChannel.size()); - - // Close the channels - srcChannel.close(); - dstChannel.close(); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - - /** - * Get the XML files in the directory. - * - * @param directoryPath - * The file system parth for the directory. - * - * @return Array of File objects that constitute an ls *.xml for the directory. - */ - public static File[] getXMLFiles(String directoryPath) - { - return getXMLFiles(new File(directoryPath)); - } - - public static File[] getXMLFilesNonRecursive(String directoryPath) - { - return getXMLFilesNonRecursive(new File(directoryPath)); - } - - /** - * Get the XML files in the directory. - * - * @param directory - * File object for the directory - * - * @return Array of File objects that constitute an ls *.xml for the directory. - */ - public static File[] getXMLFiles(File directory) - { - java.io.FileFilter XMLfilter = XMLFileFilter.get(); - return directory.isDirectory() ? directory.listFiles(XMLfilter) : null; - } - - /** - * Get XML files only in this directory - * - * @param directory - * @return - */ - public static File[] getXMLFilesNonRecursive(File directory) - { - java.io.FileFilter XMLfilter = XMLFileNonRecursiveFilter.get(); - return directory.isDirectory() ? directory.listFiles(XMLfilter) : null; - } - - /** - * Recursively delete a directory on the file system. We must recursively delete it since java - * requires that the directory be empty before deletion. - * - * @param targetDir - * The target directory to delete. - * @return true if successful, false otherwise. - */ - public static boolean deleteDirectory(File targetDir) - { - boolean succeeded = true; - - if (targetDir.exists()) - { - File[] dirFiles = targetDir.listFiles(); - for (int i = 0; i < dirFiles.length; i++) - { - File dirFile = dirFiles[i]; - if (dirFile.isDirectory()) - { - succeeded = succeeded && deleteDirectory(dirFile); - } - else - { - dirFile.delete(); - } - } - succeeded = succeeded && targetDir.delete(); - } - return succeeded; - } - - public static String getFilenameMinusExtension(File file) - { - String pathString = file.getAbsolutePath(); - return pathString.substring(pathString.lastIndexOf(sep) + 1, pathString.lastIndexOf('.')); - } - - public static boolean isZipFile(File file) throws IOException - { - BufferedInputStream fin = new BufferedInputStream(new FileInputStream(file)); - boolean isZipStream = StreamUtils.isZipStream(fin); - fin.close(); - return isZipStream; - } - - public static File findFirstExistingAncestor(File file) - { - if (file != null) - { - File parent = file.getParentFile(); - if (parent != null && parent.exists()) - return parent; - return findFirstExistingAncestor(parent); - } - return null; - } - - /** - * Given two absolute paths, find the deepest common ancestor between them. - * - * @param file1 - * @param file2 - * @return - */ - public static String findMostCommonAncestor(String file1, String file2) - { - if (file1 != null && file2 != null) - { - if (file1.length() == 0 || file2.length() == 0) - return ""; - - int file1FirstDir = file1.indexOf(File.separatorChar); - int file2FirstDir = file2.indexOf(File.separatorChar); - - if (file1FirstDir == -1 || file2FirstDir == -1) - return ""; - - String substring = file1.substring(0, file1FirstDir + 1); - if (substring.equals(file2.substring(0, file2FirstDir + 1))) - { - return substring - + findMostCommonAncestor( file1.substring(file1FirstDir + 1), - file2.substring(file2FirstDir + 1)); - } - return ""; - } - - return null; - } -} - -class XMLFileNonRecursiveFilter implements java.io.FileFilter -{ - static XMLFileNonRecursiveFilter singleton; - - static XMLFileNonRecursiveFilter get() - { - XMLFileNonRecursiveFilter result = singleton; - if (result == null) - { - result = new XMLFileNonRecursiveFilter(); - singleton = result; - } - return result; - } - - public XMLFileNonRecursiveFilter() - { - - } - - @Override - public boolean accept(File file) - { - String name = file.getName().toLowerCase(); - return name.endsWith(".xml"); - } -}// end class HTMLFileFilter - +package ecologylab.io; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.nio.channels.FileChannel; +import java.util.Date; + +import ecologylab.generic.Debug; +import ecologylab.generic.StringTools; + +/** + * A set of lovely convenience methods for doing operations on local files. + */ +public class Files extends Debug +{ + // to update, add entry here, and below in deriveLang() + public static final int NONE = -1; + + public static final int UNKNOWN = -1024; + + public static final int HTML = 0; + + public static final int JAVA = 1; + + public static final int JAVASCRIPT = 2; + + public static final int ASP = 3; + + public static final int CSS = 4; + + public static final int EXE = 5; + + public File outFile, inFile; + + public BufferedReader fileReader; + + public BufferedWriter fileWriter; + + String tempFileName; + + static String readErrorString = "Error reading from file "; + + static String writeErrorString = "Error writing to file "; + + public static final char sep = File.separatorChar; + + static public final String indent = "\t"; + + public Files() + { + } + + public Files(String inFileName) + { + setInFile(inFileName); + } + + public void setInFile(String inFileName) + { + inFile = newFile(inFileName); + } + + /** + * Create a new File object. + * + * More robust than just calling the File constructor, cause it converts all slashes to the + * direction native for the platform. + */ + public static File newFile(String inFileName) + { + return newFile((File) null, inFileName); + } + + /** + * Create a new File object. + * + * More robust than just calling the File constructor, cause it converts all slashes to the + * direction native for the platform. + */ + public static File newFile(String contextName, String inFileName) + { + return newFile(newFile(contextName), inFileName); + } + + /** + * Create a new File object. + * + * More robust than just calling the File constructor, cause it converts all slashes to the + * direction native for the platform. + */ + public static File newFile(File context, String inFileName) + { + // one of the replaces should do something; + // and the other should do nothing. + String fixedFileName = inFileName.replace('/', sep).replace('\\', sep); + File one = new File(fixedFileName); + if (context == null) + return one; + if (one.isAbsolute() || (context == null)) + { + // hack gnarly windows path shit + // (drives & backslashes are a plague on all programmers) + if (fixedFileName.length() > 1 && fixedFileName.charAt(1) != ':') + { + String contextName = context.getPath(); + if (contextName.charAt(1) == ':') + { + String fixedFixed = contextName.substring(0, 2) + fixedFileName; + return new File(fixedFixed); + } + } + return one; + } + // else + // Debug.println("newFile: (0)="+fixedFileName.charAt(0) + " (1)"+ + // fixedFileName.charAt(0)); + // if ((fixedFileName.charAt(1) == ':') || (fixedFileName.charAt(0) == sep)) + // return new File(fixedFileName); + // else + return new File(context, fixedFileName); + } + + public void close() + { + closeReader(); + closeWriter(); + } + + public boolean closeReader() + { + return closeReader(fileReader); + } + + public static boolean closeReader(BufferedReader reader) + { + boolean ok = true; + if (reader != null) + try + { + reader.close(); + } + catch (IOException ioe) + { + ok = false; + } + return ok; + } + + public boolean closeWriter() + { + return closeWriter(fileWriter); + } + + public static boolean closeWriter(BufferedWriter writer) + { + boolean ok = true; + try + { + writer.close(); + } + catch (IOException outE) + { + ok = false; + } + return ok; + } + + public static BufferedReader openReader(String fileName) + { + return openReader(newFile(fileName)); + } + + // public static BufferedReader openWebReader(String webAddr) + // { + // /* get ParsedURL from url string. */ + // ParsedURL purl = EnvironmentGeneric.getRelativeOrAbsolute(webAddr, ""); + // return openReader(purl.url()); + // } + + public static BufferedReader openReader(File file) + { + boolean ok = file.canRead(); + if (!ok) + { + println("Can't read file " + file.getAbsolutePath()); + return null; + } + println(3, "Input file: " + file); + FileReader fileReader = null; + try + { + fileReader = new FileReader(file); + return openReader(fileReader); + } + catch (FileNotFoundException e) + { + println("Can't find file " + file.getAbsolutePath()); + return null; + } + } + + public static InputStream openStream(URL url) + { + InputStream inStream = null; + try + { + URLConnection connection = url.openConnection(); + inStream = connection.getInputStream(); + } + catch (FileNotFoundException e) + { + println("Can't open because FileNotFoundException: " + url); + } + catch (IOException e) + { + println("Can't open because IOException: " + url); + } + catch (Exception e) // catch all exceptions, including security + { + println("Can't open " + url); + e.printStackTrace(); + } + return inStream; + } + + public static BufferedReader openReader(URL url) + { + InputStream inStream = openStream(url); + return (inStream == null) ? null : openReader(inStream); + } + + public static BufferedReader openReader(InputStream inStream) + { + return openReader(new InputStreamReader(inStream)); + } + + public static BufferedReader openReader(InputStreamReader inputStreamReader) + { + return new BufferedReader(inputStreamReader); + } + + public boolean openRead(File inputFile) + { + inFile = inputFile; + return openReader(); + } + + public boolean openRead(String inFileName) + { + setInFile(inFileName); + return openReader(); + } + + public static String getTempFileName(String name) + { + Date myZone = new Date(); + return sep + "temp" + sep + name + myZone.getTime(); + } + + public boolean openReader() + { + fileReader = openReader(inFile); + return (fileReader != null); + } + + public String getDir(String fullPath) + { + int index = fullPath.lastIndexOf(File.separator); + if (index == -1) + return ""; + return fullPath.substring(0, index); + } + + public boolean openWrite(String outFileName) + { + return openWrite(newFile(outFileName)); + } + + public boolean openWrite(File outDir, String outFileName) + { + return openWrite(newFile(outDir, outFileName)); + } + + public boolean openWrite(File oFile) + { + outFile = oFile; + BufferedWriter writer = openWriter(oFile); + boolean ok = (writer != null); + if (ok) + fileWriter = writer; + return ok; + } + + public static BufferedWriter openWriter(String oFileName) + { + return openWriter(newFile(oFileName)); + } + + public static BufferedWriter openWriter(String oFileName, boolean append) + { + return openWriter(newFile(oFileName), 1, append); + } + + public static BufferedWriter openWriter(File oFile, boolean append) + { + return openWriter(oFile, 1, append); + } + + public static BufferedWriter openWriter(File oFile) + { + return openWriter(oFile, 1); + } + + /** + * Make any directories necesary for the file to be written. + */ + public static boolean makePath(File oFile) + { + String oFileDirName = oFile.getParent(); + File oFileDir = newFile(oFileDirName); + boolean result = !oFileDir.equals(""); + if (result) // if ok, continue + { + result = oFileDir.exists(); + if (!result) // if exists, no more work to do + { + println("\t"); + println(oFileDir + " "); + result = oFileDir.mkdirs(); + if (!result) + Debug.println("[Making directories for you: failed.]"); + } + } + else + Debug.println("Can't write to " + oFile.getAbsolutePath()); + return result; + } + + public static BufferedWriter openWriter(File oFile, int debugLevel) + { + if (oFile == null) + return null; + + BufferedWriter writer = null; + + String oFileFullPath = oFile.getAbsolutePath(); + + println("Files.openWriter(" + oFileFullPath); + + // if (makePath(oFile)) // maybe create directories along the path + try + { + writer = new BufferedWriter(new FileWriter(oFile)); + println("\tOutput file: "); + println(indent + indent + oFileFullPath); + } + catch (IOException e) + { + Debug.println(writeErrorMsg(e, oFileFullPath)); + } + return writer; + } + + public static BufferedWriter openWriter(File oFile, int debugLevel, boolean append) + { + if (oFile == null) + return null; + BufferedWriter writer = null; + + String oFileFullPath = oFile.getAbsolutePath(); + + println("Files.openWriter(" + oFileFullPath); + + // if (makePath(oFile)) // maybe create directories along the path + try + { + writer = new BufferedWriter(new FileWriter(oFile, append)); + println("\tOutput file: "); + println(indent + indent + oFileFullPath); + } + catch (IOException e) + { + Debug.println(writeErrorMsg(e, oFileFullPath)); + } + return writer; + } + + public static FileInputStream openInStream(File inFile) + { + FileInputStream stream = null; + try + { + stream = new FileInputStream(inFile); + } + catch (Exception e) + { + Debug.println("Can't open input stream from " + inFile + " " + e); + } + return stream; + } + + public static BufferedOutputStream openOutStream(File oFile) + { + BufferedOutputStream outStream = null; + + String oFileFullPath = oFile.getAbsolutePath(); + + if (makePath(oFile)) // maybe create directories along the path + try + { + outStream = new BufferedOutputStream(new FileOutputStream(oFile)); + println(3, "Output file: "); + println(3, indent + oFileFullPath); + } + catch (IOException e) + { + Debug.println(writeErrorMsg(e, oFileFullPath)); + } + return outStream; + } + + public String readLine() + { + return readLine(fileReader); + } + + public static String readLine(BufferedReader reader) + { + String aLine = " "; + try + { + aLine = reader.readLine(); + } + catch (IOException e) + { + Debug.println(readErrorString + reader); + } + return aLine; + } + + public boolean write(String toWrite) + { + return write(fileWriter, toWrite); + } + + public static boolean write(BufferedWriter writer, String toWrite) + { + if ((toWrite == null) || (toWrite.equals(""))) + return true; + boolean ok = true; + try + { + writer.write(toWrite); + } + catch (IOException e) + { + ok = false; + Debug.println(writeErrorMsg(e, writer)); + } + return ok; + } + + // write a line of output + public boolean writeLine(String toWrite) + { + // Env.println("really writing a line"); + return writeLine(fileWriter, toWrite); + } + + public static boolean writeLine(BufferedWriter writer, String... toWrite) + { + if (toWrite == null) + return true; + boolean ok = true; + try + { + for (String sToWrite : toWrite) + writer.write(sToWrite); + writer.newLine(); + } + catch (IOException e) + { + ok = false; + // dont use Debug, to avoid infinite loops!!! + System.err.println(writeErrorMsg(e, writer)); + } + return ok; + } + + public static boolean flush(BufferedWriter writer) + { + boolean result = false; + try + { + writer.flush(); + result = true; + } + catch (IOException e) + { + + } + return result; + } + + public void rename(String finalName) + { + File newFile = newFile(finalName); + outFile.renameTo(newFile); + // Env.println("All done!!!!!"); + } + + public boolean insertFile(String fileToInsert) + { + return insertFile(fileWriter, fileToInsert); + } + + // TODO this is also old dead code + public static void copyTraceFile(File outputFile) + { + final String TRACE_PATH = System.getProperty("deployment.user.logdir") + "/plugin" + + StringTools.remove(System.getProperty("java.version"), '_') + ".trace"; + BufferedWriter writer; + BufferedReader reader; + reader = openReader(TRACE_PATH); + writer = openWriter(outputFile); + + String oneLine = readLine(reader); + + while (oneLine != null) + { + writeLine(writer, oneLine); + oneLine = readLine(reader); + } + closeReader(reader); + closeWriter(writer); + } + + public static boolean insertFile(BufferedWriter writer, String fileToInsert) + { + BufferedReader reader = openReader(fileToInsert); + boolean ok = (reader != null); + if (ok) + { + String line; + for (line = readLine(reader); line != null; line = readLine(reader)) + { + // Env.println("into " + reader + " inserting: " + line); + writeLine(writer, line); + } + } + try + { + reader.close(); + } + catch (IOException e) + { + ok = false; + } + return ok; + } + + public static boolean isDir(File file) + { + if (file.isDirectory()) + return true; + // this is a bit of a hack -- it assumes files w suffixes + String lastPart = file.getName(); + return lastPart.indexOf(".") < 0; + } + + // ????? i dunno where this was being used (CMDOC???) + // write a line of output + // public boolean writeLine(String toWrite) + // { + // return writeLine(toWrite, false); + // } + public static boolean copy(File from, File to) + { + if (!from.exists()) + { + println("I can't copy because
\n" + from.toString() + " doesn't exist."); + println(""); + return false; + } + println(2, "Copy:"); + println(2, indent + from); + println(2, indent + to); + + File dir; + if (isDir(to)) + { + dir = to; + to = newFile(to, from.getName()); + } + else + dir = newFile(to.getParent()); + + if (!dir.exists()) + dir.mkdirs(); + BufferedReader input = null; + BufferedWriter output = null; + boolean ok = true; + try + { + if (to.exists()) + to.delete(); + input = new BufferedReader(new FileReader(from)); + output = new BufferedWriter(new FileWriter(to)); + // output = new FileOutputStream(to); + } + catch (IOException e) + { + Debug.println("Files.copy error opening streams: " + e); + ok = false; + } + if (ok) + { + char buf[] = new char[32768]; // 32 K + int count = 0; + try + { + ok = false; + + while ((count = input.read(buf)) >= 0) + { + output.write(buf, 0, count); + } + ok = true; + } + catch (IOException e) + { + File errorFile = ok ? to : from; + String operation = ok ? "writing" : "reading"; + Debug.println("I/O error during copying, while " + operation + " " + + errorFile.getAbsolutePath()); + ok = false; + } + try + { + ok = false; + input.close(); + ok = true; + output.close(); + } + catch (IOException e) + { + File errorFile = ok ? to : from; + Debug.println("I/O error during copying, while closing " + errorFile.getAbsolutePath()); + ok = false; + } + } + return ok; + } + + public static String relativePath(File parent, File child) + { + String parentPath = parent.getAbsolutePath(); + String childPath = child.getAbsolutePath(); + return relativePath(parentPath, childPath); + } + + public static String relativePath(File parent, String childPath) + { + String parentPath = parent.getAbsolutePath(); + return relativePath(parentPath, childPath); + } + + public static String relativePath(String parentPath, String childPath) + { + println(3, "Relative Path:"); + println(3, indent + parentPath); + println(3, indent + childPath); + if (parentPath.equals(childPath)) + return ""; + if (childPath.indexOf(parentPath) > -1) + { + println(3, indent + childPath.substring(parentPath.length() + 1)); + return childPath.substring(parentPath.length() + 1); + } + else + return null; + } + + public static String getBeforeExtension(File file) + { + return getBeforeExtension(file.getName()); + } + + public static String getBeforeExtension(String fName) + { + String before = ""; + int dot = fName.lastIndexOf("."); + if (dot >= 0) + before = fName.substring(0, dot); + return before; + } + + public static String getExtension(File file) + { + return getExtension(file.getName()); + } + + public static String getExtension(String fName) + { + String ext = null; + int dot = fName.lastIndexOf("."); + if ((dot >= 0) && (dot < fName.length() - 1)) + ext = fName.substring(dot + 1); + return ext; + } + + public static int deriveLang(String fName) + { + int lang; + String ext = getExtension(fName); + println(4, "deriveLang got extension='" + ext + "'"); + if (ext == null) + lang = HTML; + { + ext = ext.toLowerCase(); + if (ext.equals("html") || ext.equals("htm")) + lang = HTML; + else if (ext.equals("java")) + lang = JAVA; + else if (ext.equals("js")) + lang = JAVASCRIPT; + else if (ext.equals("asp")) + lang = ASP; + else if (ext.equals("css")) + lang = CSS; + else if (ext.equals("exe")) + lang = EXE; + else + lang = UNKNOWN; + } + return lang; + } + + public static String unix(File f) + { + return f.getAbsolutePath().replace(sep, '/'); + } + + public static String unix(String s) + { + return s.replace(sep, '/'); + } + + public static boolean contains(String fileName, String s) + { + return contains(fileName, s); + } + + public static boolean contains(File f, String s) + { + BufferedReader reader = openReader(f); + for (String line = Files.readLine(reader); line != null; line = Files.readLine(reader)) + { + if (line.indexOf(s) > -1) + return true; + } + return false; + } + + public static File removeExtension(File f) + { + return (f.getName().indexOf('.') == -1) ? f : removeExtension(f.getPath()); + } + + public static File removeExtension(String path) + { + File result; + int lastDot = path.lastIndexOf('.'); + int lastSlash = path.lastIndexOf(sep); + if (lastDot > lastSlash) + { + path = path.substring(0, lastDot); + result = new File(path); + } + else + result = new File(path); + return result; + } + + // public static void main(String[] s) + // { + // // println(removeExtension(new File("c:/temp/foo.xml")).toString()); + // BufferedReader reader = openWebReader(s[0]); + // String thatLine = null; + // while ((thatLine = Files.readLine(reader)) != null) + // { + // println("read from URL " + thatLine); + // } + // closeReader(reader); + // } + + public static void main2(String[] args) throws Exception + { + URL yahoo = new URL("http://www.yahoo.com/"); + BufferedReader in = new BufferedReader(new InputStreamReader(yahoo.openStream())); + + String inputLine; + + while ((inputLine = in.readLine()) != null) + System.out.println(inputLine); + + in.close(); + } + + public static String writeErrorMsg(Throwable e, Object o) + { + return writeErrorMsg(e, o.toString()); + } + + public static String writeErrorMsg(Throwable e, File f) + { + return writeErrorMsg(e, f.getAbsolutePath()); + } + + public static String writeErrorMsg(Throwable e, String path) + { + return "Error [" + e.getMessage() + "] writing to file " + path; + } + + /** + * removes all the files in a given directory + * + * @param dir + * the dir to be cleared + */ + public static void clearDir(File dir) + { + if (dir.isDirectory()) + { + String[] children = dir.list(); + for (int i = 0; i < children.length; i++) + { + new File(dir, children[i]).delete(); + } + } + } + + /** + * copies all the files of a particular type from the src dir to the dest dir + * + * @param srcDir + * source dir + * @param dstDir + * destination dir + * @param fileType + * type of the file, for example jpg for jpeg files if fileType is null, all the files + * are copied + */ + public static void copyFiles(File srcDir, File dstDir, String fileType) + { + if (srcDir.isDirectory()) + { + String[] children = srcDir.list(); + for (int i = 0; i < children.length; i++) + { + if (fileType != null) + { + // copy only if the file is of the specified type + if (children[i].endsWith(fileType)) + copyFile(new File(srcDir, children[i]), new File(dstDir, children[i])); + } + else + { + copyFile(new File(srcDir, children[i]), new File(dstDir, children[i])); + } + } + } + } + + /** + * Copy a file -- binary or character data. + * + * @param srcFile + * @param dstFile + */ + public static void copyFile(File srcFile, File dstFile) + { + try + { + // Create channel on the source + FileChannel srcChannel = new FileInputStream(srcFile).getChannel(); + + // Create channel on the destination + FileChannel dstChannel = new FileOutputStream(dstFile).getChannel(); + + // Copy file contents from source to destination + dstChannel.transferFrom(srcChannel, 0, srcChannel.size()); + + // Close the channels + srcChannel.close(); + dstChannel.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + /** + * Get the XML files in the directory. + * + * @param directoryPath + * The file system parth for the directory. + * + * @return Array of File objects that constitute an ls *.xml for the directory. + */ + public static File[] getXMLFiles(String directoryPath) + { + return getXMLFiles(new File(directoryPath)); + } + + public static File[] getXMLFilesNonRecursive(String directoryPath) + { + return getXMLFilesNonRecursive(new File(directoryPath)); + } + + /** + * Get the XML files in the directory. + * + * @param directory + * File object for the directory + * + * @return Array of File objects that constitute an ls *.xml for the directory. + */ + public static File[] getXMLFiles(File directory) + { + java.io.FileFilter XMLfilter = XMLFileFilter.get(); + return directory.isDirectory() ? directory.listFiles(XMLfilter) : null; + } + + /** + * Get XML files only in this directory + * + * @param directory + * @return + */ + public static File[] getXMLFilesNonRecursive(File directory) + { + java.io.FileFilter XMLfilter = XMLFileNonRecursiveFilter.get(); + return directory.isDirectory() ? directory.listFiles(XMLfilter) : null; + } + + /** + * Recursively delete a directory on the file system. We must recursively delete it since java + * requires that the directory be empty before deletion. + * + * @param targetDir + * The target directory to delete. + * @return true if successful, false otherwise. + */ + public static boolean deleteDirectory(File targetDir) + { + boolean succeeded = true; + + if (targetDir.exists()) + { + File[] dirFiles = targetDir.listFiles(); + for (int i = 0; i < dirFiles.length; i++) + { + File dirFile = dirFiles[i]; + if (dirFile.isDirectory()) + { + succeeded = succeeded && deleteDirectory(dirFile); + } + else + { + dirFile.delete(); + } + } + succeeded = succeeded && targetDir.delete(); + } + return succeeded; + } + + public static String getFilenameMinusExtension(File file) + { + String pathString = file.getAbsolutePath(); + return pathString.substring(pathString.lastIndexOf(sep) + 1, pathString.lastIndexOf('.')); + } + + public static boolean isZipFile(File file) throws IOException + { + BufferedInputStream fin = new BufferedInputStream(new FileInputStream(file)); + boolean isZipStream = StreamUtils.isZipStream(fin); + fin.close(); + return isZipStream; + } + + public static File findFirstExistingAncestor(File file) + { + if (file != null) + { + File parent = file.getParentFile(); + if (parent != null && parent.exists()) + return parent; + return findFirstExistingAncestor(parent); + } + return null; + } + + /** + * Given two absolute paths, find the deepest common ancestor between them. + * + * @param file1 + * @param file2 + * @return + */ + public static String findMostCommonAncestor(String file1, String file2) + { + if (file1 != null && file2 != null) + { + if (file1.length() == 0 || file2.length() == 0) + return ""; + + int file1FirstDir = file1.indexOf(File.separatorChar); + int file2FirstDir = file2.indexOf(File.separatorChar); + + if (file1FirstDir == -1 || file2FirstDir == -1) + return ""; + + String substring = file1.substring(0, file1FirstDir + 1); + if (substring.equals(file2.substring(0, file2FirstDir + 1))) + { + return substring + + findMostCommonAncestor( file1.substring(file1FirstDir + 1), + file2.substring(file2FirstDir + 1)); + } + return ""; + } + + return null; + } +} + +class XMLFileNonRecursiveFilter implements java.io.FileFilter +{ + static XMLFileNonRecursiveFilter singleton; + + static XMLFileNonRecursiveFilter get() + { + XMLFileNonRecursiveFilter result = singleton; + if (result == null) + { + result = new XMLFileNonRecursiveFilter(); + singleton = result; + } + return result; + } + + public XMLFileNonRecursiveFilter() + { + + } + + @Override + public boolean accept(File file) + { + String name = file.getName().toLowerCase(); + return name.endsWith(".xml"); + } +}// end class HTMLFileFilter + diff --git a/simplCore/src/ecologylab/io/LockFile.java b/simplCore/src/ecologylab/io/LockFile.java index ba9873c1..171db468 100644 --- a/simplCore/src/ecologylab/io/LockFile.java +++ b/simplCore/src/ecologylab/io/LockFile.java @@ -1,124 +1,124 @@ -package ecologylab.io; - -import java.io.File; -import java.io.IOException; - -import ecologylab.appframework.PropertiesAndDirectories; -import ecologylab.generic.Debug; - -/** - * Simple utility to write and detect lock files. - * - * @author blake - */ -public class LockFile -extends Debug -{ - String programName; - File lockFile = null; - - /** - * Takes a program name to check/generate lockfile state. - * - * @param uniqueProgramName The unique name of the program concerned with locking. - */ - public LockFile(String uniqueProgramName) - { - programName = uniqueProgramName; - } - - /** - * Lock the program (create a lockfile). Return a status. - * @return whether or not the lockfile could be sucessfully written. - */ - public boolean lock() - { - if (!isLocked()) - { - try - { - lockFile.createNewFile(); - } - catch (IOException e) - { - System.out.println("LockfileUtility: failed to create lockfile: " + programName); - return false; - } - return true; - } - else - { - return false; - } - - } - - /** - * Unlock the program (delete the lockfile). Return a status. - * @return whether or not the lockfile could be sucessfully deleted. - */ - public boolean unlock() - { - if (lockFile == null) - lockFile = getLockFile(); - - lockFile.delete(); - //lockFile = null; - return true; - } - - /** - * Determine weather or not the program is locked right now. This is NEVER cached. - * - * @return whether or not this program is locked. - */ - public boolean isLocked() - { - if (lockFile == null) - lockFile = getLockFile(); - - return (lockFile != null && lockFile.exists()); - } - static final int THIRTY_SECONDS = 1000 * 30; - /** - * Return true if the lock file exists, and is older than 90 seconds ago. - * @return - */ - public boolean isOld() - { - if (!isLocked()) - return false; - long lastMod = lockFile.lastModified(); - long now = System.currentTimeMillis(); - long deltaT = now - lastMod; - debug("Checking lock file; its age is " + deltaT); - return isLocked() && (deltaT >= THIRTY_SECONDS); - } - /** - * Gets rid of the file handler (for garbage collection) - * - */ - public void close() - { - if (lockFile != null) - lockFile = null; - } - - /** - * Gets a File reference to the actual file lock. - * - * @return The file lock. - */ - public File getFileLock() - { - return lockFile; - } - - private File getLockFile() - { - String lockName = "." + programName + ".lock"; - return new File(PropertiesAndDirectories.tempDir(), - lockName); - } - -} +package ecologylab.io; + +import java.io.File; +import java.io.IOException; + +import ecologylab.appframework.PropertiesAndDirectories; +import ecologylab.generic.Debug; + +/** + * Simple utility to write and detect lock files. + * + * @author blake + */ +public class LockFile +extends Debug +{ + String programName; + File lockFile = null; + + /** + * Takes a program name to check/generate lockfile state. + * + * @param uniqueProgramName The unique name of the program concerned with locking. + */ + public LockFile(String uniqueProgramName) + { + programName = uniqueProgramName; + } + + /** + * Lock the program (create a lockfile). Return a status. + * @return whether or not the lockfile could be sucessfully written. + */ + public boolean lock() + { + if (!isLocked()) + { + try + { + lockFile.createNewFile(); + } + catch (IOException e) + { + System.out.println("LockfileUtility: failed to create lockfile: " + programName); + return false; + } + return true; + } + else + { + return false; + } + + } + + /** + * Unlock the program (delete the lockfile). Return a status. + * @return whether or not the lockfile could be sucessfully deleted. + */ + public boolean unlock() + { + if (lockFile == null) + lockFile = getLockFile(); + + lockFile.delete(); + //lockFile = null; + return true; + } + + /** + * Determine weather or not the program is locked right now. This is NEVER cached. + * + * @return whether or not this program is locked. + */ + public boolean isLocked() + { + if (lockFile == null) + lockFile = getLockFile(); + + return (lockFile != null && lockFile.exists()); + } + static final int THIRTY_SECONDS = 1000 * 30; + /** + * Return true if the lock file exists, and is older than 90 seconds ago. + * @return + */ + public boolean isOld() + { + if (!isLocked()) + return false; + long lastMod = lockFile.lastModified(); + long now = System.currentTimeMillis(); + long deltaT = now - lastMod; + debug("Checking lock file; its age is " + deltaT); + return isLocked() && (deltaT >= THIRTY_SECONDS); + } + /** + * Gets rid of the file handler (for garbage collection) + * + */ + public void close() + { + if (lockFile != null) + lockFile = null; + } + + /** + * Gets a File reference to the actual file lock. + * + * @return The file lock. + */ + public File getFileLock() + { + return lockFile; + } + + private File getLockFile() + { + String lockName = "." + programName + ".lock"; + return new File(PropertiesAndDirectories.tempDir(), + lockName); + } + +} diff --git a/simplCore/src/ecologylab/io/NIOTools.java b/simplCore/src/ecologylab/io/NIOTools.java index 18f7c18e..03c4418f 100644 --- a/simplCore/src/ecologylab/io/NIOTools.java +++ b/simplCore/src/ecologylab/io/NIOTools.java @@ -1,162 +1,162 @@ -package ecologylab.io; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.lang.reflect.Method; -import java.nio.ByteBuffer; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; -import java.security.AccessController; -import java.security.PrivilegedAction; - -import ecologylab.generic.Debug; - -/** - * Utility class for managing memory mapped buffers. - * - * @author wolf - */ -public class NIOTools extends Debug -{ - /** - * The logger for reporting io problems - */ - private static boolean warned; - - /** - * Really closes a MappedByteBuffer without the need to wait for garbage collection. Any problems - * with closing a buffer on Windows (the problem child in this case) will be logged as SEVERE to - * the logger of the package name. To force logging of errors, set the System property - * "org.geotools.io.debugBuffer" to "true". - * - * @param buffer - * See MappedByteBuffer - * @return true if the operation was successful, false otherwise. - */ - public static boolean clean(final java.nio.ByteBuffer buffer) - { - if (buffer == null || !buffer.isDirect()) - return false; - - Boolean b = (Boolean) AccessController.doPrivileged(new PrivilegedAction() - { - @Override - public Object run() - { - Boolean success = Boolean.FALSE; - try - { - Method getCleanerMethod = buffer.getClass().getMethod("cleaner", null); - getCleanerMethod.setAccessible(true); - Object cleaner = getCleanerMethod.invoke(buffer, null); - Method clean = cleaner.getClass().getMethod("clean", null); - clean.invoke(cleaner, null); - success = Boolean.TRUE; - } - catch (Exception e) - { - if (!warned) - log(e, buffer); - } - return success; - } - }); - - return b.booleanValue(); - } - - private static void log(Exception e, java.nio.ByteBuffer buffer) - { - warned = true; - String message = "NIOTools: Error attempting to close a mapped byte buffer : " - + buffer.getClass().getName(); - message += "\n JVM : " + System.getProperty("java.version") + " " - + System.getProperty("java.vendor"); - Debug.println(message); - } - - public static boolean writeMemoryMapped(File file, StringBuilder buffy) - { - boolean ok = true; - RandomAccessFile rFile = null; - MappedByteBuffer mMapBuffer = null; - try - { - rFile = new RandomAccessFile(file, "rw"); - FileChannel fileChannel = rFile.getChannel(); - - int length = buffy.length(); - - mMapBuffer = fileChannel.map(FileChannel.MapMode.PRIVATE, 0, length); - fileChannel.close(); - // TODO could write XmlTools.xmlHeader() here - - for (int i = 0; i < length; i++) - mMapBuffer.put((byte) buffy.charAt(i)); - - rFile.close(); - clean(mMapBuffer); - } - catch (IOException e) - { - e.printStackTrace(); - ok = false; - } - /* - * finally { try { if (rFile != null) rFile.close(); } catch (IOException e) { - * e.printStackTrace(); } if (mMapBuffer != null) clean(mMapBuffer); } - */ - return ok; - } - - static final int BUFFER_SIZE = 1024; - - static final ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER_SIZE); - - public static boolean writeFile(File file, StringBuilder buffy) - { - boolean ok = true; - FileOutputStream oStream = null; - - try - { - oStream = new FileOutputStream(file); - FileChannel fileChannel = oStream.getChannel(); - - int length = buffy.length(); - // TODO could write XmlTools.xmlHeader() here - - int buffyIndex = 0; - for (buffyIndex = 0; buffyIndex < length; buffyIndex += BUFFER_SIZE) - { - writeABuffer(fileChannel, buffy, buffyIndex, BUFFER_SIZE); - // TODO -- deal with how this will drop bytes at the end - } - if (buffyIndex > length) - { - buffyIndex -= BUFFER_SIZE; - int lastCount = length - buffyIndex; - // writeABuffer(fileChannel, buffy, buffyIndex, lastCount); - } - fileChannel.close(); - } - catch (IOException e) - { - e.printStackTrace(); - ok = false; - } - return ok; - } - - private static void writeABuffer(FileChannel fileChannel, StringBuilder buffy, int index, - int length) throws IOException - { - for (int i = 0; i < length; i++) - byteBuffer.put((byte) buffy.charAt(index)); - - fileChannel.write(byteBuffer); - byteBuffer.clear(); - } -} +package ecologylab.io; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import ecologylab.generic.Debug; + +/** + * Utility class for managing memory mapped buffers. + * + * @author wolf + */ +public class NIOTools extends Debug +{ + /** + * The logger for reporting io problems + */ + private static boolean warned; + + /** + * Really closes a MappedByteBuffer without the need to wait for garbage collection. Any problems + * with closing a buffer on Windows (the problem child in this case) will be logged as SEVERE to + * the logger of the package name. To force logging of errors, set the System property + * "org.geotools.io.debugBuffer" to "true". + * + * @param buffer + * See MappedByteBuffer + * @return true if the operation was successful, false otherwise. + */ + public static boolean clean(final java.nio.ByteBuffer buffer) + { + if (buffer == null || !buffer.isDirect()) + return false; + + Boolean b = (Boolean) AccessController.doPrivileged(new PrivilegedAction() + { + @Override + public Object run() + { + Boolean success = Boolean.FALSE; + try + { + Method getCleanerMethod = buffer.getClass().getMethod("cleaner", null); + getCleanerMethod.setAccessible(true); + Object cleaner = getCleanerMethod.invoke(buffer, null); + Method clean = cleaner.getClass().getMethod("clean", null); + clean.invoke(cleaner, null); + success = Boolean.TRUE; + } + catch (Exception e) + { + if (!warned) + log(e, buffer); + } + return success; + } + }); + + return b.booleanValue(); + } + + private static void log(Exception e, java.nio.ByteBuffer buffer) + { + warned = true; + String message = "NIOTools: Error attempting to close a mapped byte buffer : " + + buffer.getClass().getName(); + message += "\n JVM : " + System.getProperty("java.version") + " " + + System.getProperty("java.vendor"); + Debug.println(message); + } + + public static boolean writeMemoryMapped(File file, StringBuilder buffy) + { + boolean ok = true; + RandomAccessFile rFile = null; + MappedByteBuffer mMapBuffer = null; + try + { + rFile = new RandomAccessFile(file, "rw"); + FileChannel fileChannel = rFile.getChannel(); + + int length = buffy.length(); + + mMapBuffer = fileChannel.map(FileChannel.MapMode.PRIVATE, 0, length); + fileChannel.close(); + // TODO could write XmlTools.xmlHeader() here + + for (int i = 0; i < length; i++) + mMapBuffer.put((byte) buffy.charAt(i)); + + rFile.close(); + clean(mMapBuffer); + } + catch (IOException e) + { + e.printStackTrace(); + ok = false; + } + /* + * finally { try { if (rFile != null) rFile.close(); } catch (IOException e) { + * e.printStackTrace(); } if (mMapBuffer != null) clean(mMapBuffer); } + */ + return ok; + } + + static final int BUFFER_SIZE = 1024; + + static final ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER_SIZE); + + public static boolean writeFile(File file, StringBuilder buffy) + { + boolean ok = true; + FileOutputStream oStream = null; + + try + { + oStream = new FileOutputStream(file); + FileChannel fileChannel = oStream.getChannel(); + + int length = buffy.length(); + // TODO could write XmlTools.xmlHeader() here + + int buffyIndex = 0; + for (buffyIndex = 0; buffyIndex < length; buffyIndex += BUFFER_SIZE) + { + writeABuffer(fileChannel, buffy, buffyIndex, BUFFER_SIZE); + // TODO -- deal with how this will drop bytes at the end + } + if (buffyIndex > length) + { + buffyIndex -= BUFFER_SIZE; + int lastCount = length - buffyIndex; + // writeABuffer(fileChannel, buffy, buffyIndex, lastCount); + } + fileChannel.close(); + } + catch (IOException e) + { + e.printStackTrace(); + ok = false; + } + return ok; + } + + private static void writeABuffer(FileChannel fileChannel, StringBuilder buffy, int index, + int length) throws IOException + { + for (int i = 0; i < length; i++) + byteBuffer.put((byte) buffy.charAt(index)); + + fileChannel.write(byteBuffer); + byteBuffer.clear(); + } +} diff --git a/simplCore/src/ecologylab/io/NamedInputStream.java b/simplCore/src/ecologylab/io/NamedInputStream.java new file mode 100644 index 00000000..fe2dae6e --- /dev/null +++ b/simplCore/src/ecologylab/io/NamedInputStream.java @@ -0,0 +1,37 @@ +package ecologylab.io; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; + +/** + * Bundle a nice printable string for error messages with an InputStream. + * + * @author andruid + */ +public class NamedInputStream +{ + final String name; + final InputStream inputStream; + + public NamedInputStream(String name, InputStream stream) + { + this.name = name; + this.inputStream = stream; + } + public NamedInputStream(File file) throws FileNotFoundException + { + this.name = file.getName(); + this.inputStream = new FileInputStream(file); + } + public String getName() + { + return name; + } + + public InputStream getInputStream() + { + return inputStream; + } +} diff --git a/simplCore/src/ecologylab/io/StreamUtils.java b/simplCore/src/ecologylab/io/StreamUtils.java index 7907ed9f..1305811c 100644 --- a/simplCore/src/ecologylab/io/StreamUtils.java +++ b/simplCore/src/ecologylab/io/StreamUtils.java @@ -1,72 +1,72 @@ -package ecologylab.io; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import ecologylab.generic.Debug; - -/** - * Utility methods for operating on streams. - * - * @author blake - * - */ -public class StreamUtils -{ - public static final void copyFile(File in, File out) - throws IOException - { - copyInputStream(new FileInputStream(in), new FileOutputStream(out)); - } - /** - * Tiny inner class to handle buffer I/O - * - * @param in The inputstream - * @param out The outputstream - * @throws IOException Throws IOException on invalid in or out stream. - */ - public static final void copyInputStream(InputStream in, OutputStream out) - throws IOException - { - //TODO use a buffer pool! - byte[] buffer = new byte[1024]; - int len; - - while((len = in.read(buffer)) >= 0) - out.write(buffer, 0, len); - - in.close(); - out.close(); - } - - /** - * this method uses the local file header signature to detect if an input stream is a zip - * stream. for zip files this header signature is 50 4B 03 04. note that this is not 100% - * accuracy: the stream may just happen to start with this signature, or it may be corrupted. - * - * @param in - * @return - * @throws IOException - */ - public static boolean isZipStream(InputStream in) throws IOException - { - if (!in.markSupported()) - { - Debug.error(StreamUtils.class, - "isZipStream(): mark/reset not supported for this input stream: cannot detect if this is a zip stream!"); - return false; - } - in.mark(4); - byte[] sig = new byte[4]; - in.read(sig); - in.reset(); - if (sig[0] == 0x50 && sig[1] == 0x4b && sig[2] == 0x03 && sig[3] == 0x04) - return true; - return false; - } - -} +package ecologylab.io; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import ecologylab.generic.Debug; + +/** + * Utility methods for operating on streams. + * + * @author blake + * + */ +public class StreamUtils +{ + public static final void copyFile(File in, File out) + throws IOException + { + copyInputStream(new FileInputStream(in), new FileOutputStream(out)); + } + /** + * Tiny inner class to handle buffer I/O + * + * @param in The inputstream + * @param out The outputstream + * @throws IOException Throws IOException on invalid in or out stream. + */ + public static final void copyInputStream(InputStream in, OutputStream out) + throws IOException + { + //TODO use a buffer pool! + byte[] buffer = new byte[1024]; + int len; + + while((len = in.read(buffer)) >= 0) + out.write(buffer, 0, len); + + in.close(); + out.close(); + } + + /** + * this method uses the local file header signature to detect if an input stream is a zip + * stream. for zip files this header signature is 50 4B 03 04. note that this is not 100% + * accuracy: the stream may just happen to start with this signature, or it may be corrupted. + * + * @param in + * @return + * @throws IOException + */ + public static boolean isZipStream(InputStream in) throws IOException + { + if (!in.markSupported()) + { + Debug.error(StreamUtils.class, + "isZipStream(): mark/reset not supported for this input stream: cannot detect if this is a zip stream!"); + return false; + } + in.mark(4); + byte[] sig = new byte[4]; + in.read(sig); + in.reset(); + if (sig[0] == 0x50 && sig[1] == 0x4b && sig[2] == 0x03 && sig[3] == 0x04) + return true; + return false; + } + +} diff --git a/simplCore/src/ecologylab/io/XMLFileFilter.java b/simplCore/src/ecologylab/io/XMLFileFilter.java index 0f019235..94a83e93 100644 --- a/simplCore/src/ecologylab/io/XMLFileFilter.java +++ b/simplCore/src/ecologylab/io/XMLFileFilter.java @@ -1,31 +1,31 @@ -package ecologylab.io; - -import java.io.File; -import java.io.FileFilter; - -public class XMLFileFilter implements FileFilter -{ - static XMLFileFilter singleton; - - static XMLFileFilter get() - { - XMLFileFilter result = singleton; - if (result == null) - { - result = new XMLFileFilter(); - singleton = result; - } - return result; - } - public XMLFileFilter() - { - - } - @Override - public boolean accept(File file) - { - if (file.isDirectory()) return true; - String name = file.getName().toLowerCase(); - return name.endsWith(".xml"); - } -} +package ecologylab.io; + +import java.io.File; +import java.io.FileFilter; + +public class XMLFileFilter implements FileFilter +{ + static XMLFileFilter singleton; + + static XMLFileFilter get() + { + XMLFileFilter result = singleton; + if (result == null) + { + result = new XMLFileFilter(); + singleton = result; + } + return result; + } + public XMLFileFilter() + { + + } + @Override + public boolean accept(File file) + { + if (file.isDirectory()) return true; + String name = file.getName().toLowerCase(); + return name.endsWith(".xml"); + } +} diff --git a/simplCore/src/ecologylab/io/ZipDownload.java b/simplCore/src/ecologylab/io/ZipDownload.java index 3ab9bd2c..87f96a6c 100644 --- a/simplCore/src/ecologylab/io/ZipDownload.java +++ b/simplCore/src/ecologylab/io/ZipDownload.java @@ -1,502 +1,502 @@ -/** - * Simple class to download and write zip files to disk. - */ -package ecologylab.io; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URLConnection; -import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import ecologylab.appframework.StatusReporter; -import ecologylab.concurrent.BasicSite; -import ecologylab.concurrent.Downloadable; -import ecologylab.concurrent.DownloadableLogRecord; -import ecologylab.generic.Continuation; -import ecologylab.generic.Debug; -import ecologylab.net.NetTools; -import ecologylab.net.ParsedURL; - -/** - * Class implementing DownloadLoadable to allow for the downloading and writing to disk of zip - * files. Additionally files can be extracted after downloaded. - * - * @author Blake Dworaczyk - */ -public class ZipDownload extends Debug implements Downloadable, Continuation -{ - - static DownloadProcessor downloadProcessor; - - ParsedURL zipSource; - - File zipTarget; - - StatusReporter status; - - boolean keepStatus = false; - - boolean downloadDone = false; - - boolean downloadStarted = false; - - boolean aborted = false; - - boolean extractWhenComplete = false; - - int fileSize = -1; - - InputStream inputStream = null; - - private static final int BUFFER_SIZE = 8192; - - public ZipDownload(ParsedURL zipSource, File zipTarget, StatusReporter status) - { - super(); - - this.zipSource = zipSource; - this.zipTarget = zipTarget; - this.status = status; - - if (status != null) - keepStatus = true; - } - - public ZipDownload(ParsedURL zipSource, File zipTarget) - { - this(zipSource, zipTarget, null); - } - - /** - * Initiate the download and writing of the zip file. This is called by outsiders. - * - * @throws IOException - */ - public void downloadAndWrite(boolean extractWhenComplete) throws IOException - { - this.extractWhenComplete = extractWhenComplete; - debug("downloadAndWrite() calling downloadMonitor"); - if (downloadProcessor == null) - throw new RuntimeException("Can't download cause downloadProcessor = null."); - - downloadProcessor.download(this, this); - } - - public static void stopDownloadProcessor() - { - if (downloadProcessor != null) - downloadProcessor.stop(); - } - - public void downloadAndWrite() throws IOException - { - downloadAndWrite(false); - } - - /** - * ONLY called by DownloadProcessors to actually download the zip file! Not called by - * outsiders! - * - * @throws IOException - */ - @Override - public void performDownload() throws IOException - { -// debug("performDOwnload() top"); - if (downloadStarted) - return; - - downloadStarted = true; - - // this gets the stream and sets the member field 'fileSize' - // inputStream = getInputStream(zipSource); - inputStream = zipSource.url().openStream(); - - debug("performDownload() got InputStream"); - - // actually read and write the zip - // if zipTarget already exists, delete it - if (zipTarget.exists()) - { - boolean deleted = zipTarget.delete(); - debug("ZipTarget exists, so deleting = " + deleted); - } - - OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(zipTarget)); - debug("performDownload() got outputStream from " + zipTarget); - - byte zipBytes[] = new byte[BUFFER_SIZE]; - - // Read data from the source file and write it out to the zip file - int count = 0; - int lastTenth = 1; - int incrementSize = fileSize / 10; - // int i=0; - while ((count = inputStream.read(zipBytes, 0, BUFFER_SIZE)) != -1) - { - if (status != null) - { - // Our status will be in 10% increments - if (count >= incrementSize * (lastTenth)) - status.display("Downloading zip file " + zipTarget.getName(), 1, count / 10, - incrementSize); - - // can't just increment because we maybe skip/hit 1/10ths due to - // faster/slower transfer rates, traffic, etc. - lastTenth = (int) Math.floor(((double) count / fileSize) * 10); - } - outputStream.write(zipBytes, 0, count); - } - - outputStream.close(); - inputStream.close(); - - if (extractWhenComplete) - extractZipFile(zipTarget); - - synchronized (this) - { - downloadDone = true; - } - } - - public BufferedInputStream getInputStream(File zipTarget) throws Exception - { - URLConnection urlConnection; - - if (zipTarget.isDirectory()) - { - - throw new Exception("ZipDownload: write exception! Can't write to directory!"); - } - - if (zipSource.isFile()) - { - inputStream = new FileInputStream(zipSource.file()); - - } - // In case the purl was constructed with a local file used as a URL - // TODO find the source of these bad constructions! (only applicabale when cF is launched as an - // application) - else if (zipSource.toString().startsWith("file://")) - { - try - { - File fileInput = new File(zipSource.toString().substring(7, zipSource.toString().length())); - inputStream = new FileInputStream(fileInput); - } - catch (Exception e) - { - System.out.println("ZipDownload: error reading local file"); - e.printStackTrace(); - throw new Exception("ZipDownload: IOException"); - } - } - else - { - urlConnection = zipSource.url().openConnection(); - if ((urlConnection == null) || aborted) - { - System.err.println("Cant open URLConnection for " + aborted + " " + zipSource); - throw new Exception("ZipDownload: IOException"); - } - try - { - urlConnection.connect(); - fileSize = urlConnection.getContentLength(); - inputStream = urlConnection.getInputStream(); - } - catch (FileNotFoundException e) - { - System.err.println("FileNotFound!"); - throw new Exception("ZipDownload: IOException"); - } - } - if ((inputStream == null) || aborted) - { - System.err.println("Cant open InputStream for " + aborted + " " + zipSource); - throw new Exception("ZipDownload: IOException"); - } - - return new BufferedInputStream(inputStream); - } - - public boolean isDownloadDone() - { - return downloadDone; - } - - @Override - public void handleIoError(Throwable e) - { - aborted = true; - NetTools.close(inputStream); - } - - @Override - public String toString() - { - return "ZipDownload() " + zipSource + " -> " + zipTarget; - } - - @Override - public void callback(Object o) - { - System.out.println("ZipDownload delivered: " + (o)); - } - - /** - * Convenience function to allow downloading and uncompressing of a zip file from a source to a - * target location with minimal effort. - * - * @param sourceZip - * The location of the zip file to download and uncompress. - * @param targetDir - * The location where the zip file should be uncompressed. This directory structure will - * be created if it doesn't exist. - * @param status - * The StatusReporter object that provides a source of state change visiblity; can be - * null. - * @param unCompress - * true if the file is a zip that needs to be uncompressed after download. - * @return TODO - */ - public static ZipDownload downloadAndPerhapsUncompress(ParsedURL sourceZip, File targetDir, - StatusReporter status, boolean unCompress) - { - // Create the target parent directory. - if (!targetDir.exists()) - targetDir.mkdirs(); - - println("downloading from zip URL: " + sourceZip + "\n\t to " + targetDir); - try - { - // FIXME make this use a (fixed?!) version of ParsedURL.isFile() ... - // if (sourceZip.toString().startsWith("file://")) - if (sourceZip.isFile()) - { - // copy zip file from assets source to cache - File sourceZipFile = sourceZip.file(); - String fileName = sourceZipFile.getName(); - File destFile = Files.newFile(targetDir, fileName); - File destFileDir = Files.newFile(targetDir, - destFile.toString().substring(0, destFile.toString().length() - 4)); - - println("Checking if dir exists: " + destFileDir.toString()); - - // Delete the previous directory if it exists. - if (destFileDir.exists()) - Files.deleteDirectory(destFileDir); - - StreamUtils.copyFile(sourceZipFile, destFile); - extractZipFile(sourceZipFile, targetDir); - - return null; - } - else - { - String fileName = sourceZip.getName(); - ZipDownload zipDownload = new ZipDownload(sourceZip, Files.newFile(targetDir, fileName), - status); - zipDownload.downloadAndWrite(unCompress); - return zipDownload; - } - } - catch (IOException e) - { - System.err.println("Error, zip file not found on the server!"); - // hiding stack trace -- it's annoying. - // e.printStackTrace(); - return null; - } - } - - /** - * Extracts a zip file into the directory where it resides - * - * @param zipSourcePath - * The path to the source zip file to extract. - */ - public static void extractZipFile(String zipSourcePath) throws IOException - { - extractZipFile(new File(zipSourcePath)); - } - - public static void extractZipFile(File zipSource) throws IOException - { - extractZipFile(zipSource, zipSource.getParentFile()); - } - - /** - * Extracts a zip file into the directory where it resides - * - * @param zipSourcePath - * The source zip file to extract - */ - public static void extractZipFile(String zipSourcePath, File unzipPath) throws IOException - { - extractZipFile(new File(zipSourcePath), unzipPath); - } - - /** - * Extracts a zip file into the directory where it resides - * - * @param zipSource - * The source zip file to extract - */ - public static void extractZipFile(File zipSource, File unzipPath) throws IOException - { - ZipFile zipFile = new ZipFile(zipSource); - System.out.println("Extracting zip file: " + zipSource); - Enumeration entries = zipFile.entries(); - while (entries.hasMoreElements()) - { - ZipEntry entry = (ZipEntry) entries.nextElement(); - String entryName = entry.getName(); - if (entry.isDirectory()) - { - File entryDir = new File(unzipPath, entryName); - if (!entryDir.exists()) - entryDir.mkdirs(); - - continue; - } - // else (if !entry.ex) - File outFile = new File(unzipPath, entryName); - String dirPath = outFile.getParent(); - File dir = new File(dirPath); - if (!dir.exists()) - dir.mkdirs(); - StreamUtils.copyInputStream(zipFile.getInputStream(entry), new BufferedOutputStream( - new FileOutputStream(outFile))); - } - - zipFile.close(); - - System.out.println("Finished extracting Zip file to " + unzipPath); - } - - /** - * Call to notify the object that its download is completed; - * - */ - public synchronized void downloadDone() - { - notifyAll(); - } - - public void waitForDownload() - { - synchronized (this) - { - if (!downloadDone && !aborted) - { - try - { - wait(); - } - catch (InterruptedException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - } - - public static void setDownloadProcessor(DownloadProcessor downloadProcessor) - { - ZipDownload.downloadProcessor = downloadProcessor; - } - - @Override - public boolean isRecycled() - { - // TODO Auto-generated method stub - return false; - } - - @Override - public BasicSite getSite() - { - // TODO Auto-generated method stub - return null; - } - - /** - * - * @return What to tell the user about what is being downloaded. - */ - @Override - public String message() - { - return "zip archive " + zipSource.toString(); - } - - @Override - public ParsedURL location() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public void recycle() - { - if (inputStream != null) - try - { - inputStream.close(); - } - catch (IOException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - /** - * Default empty implementation; will be ignored for this type. - */ - @Override - public boolean isImage() - { - return false; - } - - @Override - public BasicSite getDownloadSite() - { - return null; - } - - @Override - public ParsedURL getDownloadLocation() - { - return location(); - } - - @Override - public boolean isCached() - { - // TODO Auto-generated method stub - return false; - } - - @Override - public DownloadableLogRecord getLogRecord() - { - // TODO Auto-generated method stub - return null; - } - -} +/** + * Simple class to download and write zip files to disk. + */ +package ecologylab.io; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URLConnection; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import ecologylab.appframework.StatusReporter; +import ecologylab.concurrent.Downloadable; +import ecologylab.concurrent.DownloadableLogRecord; +import ecologylab.concurrent.Site; +import ecologylab.generic.Continuation; +import ecologylab.generic.Debug; +import ecologylab.net.NetTools; +import ecologylab.net.ParsedURL; + +/** + * Class implementing DownloadLoadable to allow for the downloading and writing to disk of zip + * files. Additionally files can be extracted after downloaded. + * + * @author Blake Dworaczyk + */ +public class ZipDownload extends Debug implements Downloadable, Continuation +{ + + static DownloadProcessor downloadProcessor; + + ParsedURL zipSource; + + File zipTarget; + + StatusReporter status; + + boolean keepStatus = false; + + boolean downloadDone = false; + + boolean downloadStarted = false; + + boolean aborted = false; + + boolean extractWhenComplete = false; + + int fileSize = -1; + + InputStream inputStream = null; + + private static final int BUFFER_SIZE = 8192; + + public ZipDownload(ParsedURL zipSource, File zipTarget, StatusReporter status) + { + super(); + + this.zipSource = zipSource; + this.zipTarget = zipTarget; + this.status = status; + + if (status != null) + keepStatus = true; + } + + public ZipDownload(ParsedURL zipSource, File zipTarget) + { + this(zipSource, zipTarget, null); + } + + /** + * Initiate the download and writing of the zip file. This is called by outsiders. + * + * @throws IOException + */ + public void downloadAndWrite(boolean extractWhenComplete) throws IOException + { + this.extractWhenComplete = extractWhenComplete; + debug("downloadAndWrite() calling downloadMonitor"); + if (downloadProcessor == null) + throw new RuntimeException("Can't download cause downloadProcessor = null."); + + downloadProcessor.download(this, this); + } + + public static void stopDownloadProcessor() + { + if (downloadProcessor != null) + downloadProcessor.stop(); + } + + public void downloadAndWrite() throws IOException + { + downloadAndWrite(false); + } + + /** + * ONLY called by DownloadProcessors to actually download the zip file! Not called by + * outsiders! + * + * @throws IOException + */ + @Override + public void performDownload() throws IOException + { +// debug("performDOwnload() top"); + if (downloadStarted) + return; + + downloadStarted = true; + + // this gets the stream and sets the member field 'fileSize' + // inputStream = getInputStream(zipSource); + inputStream = zipSource.url().openStream(); + + debug("performDownload() got InputStream"); + + // actually read and write the zip + // if zipTarget already exists, delete it + if (zipTarget.exists()) + { + boolean deleted = zipTarget.delete(); + debug("ZipTarget exists, so deleting = " + deleted); + } + + OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(zipTarget)); + debug("performDownload() got outputStream from " + zipTarget); + + byte zipBytes[] = new byte[BUFFER_SIZE]; + + // Read data from the source file and write it out to the zip file + int count = 0; + int lastTenth = 1; + int incrementSize = fileSize / 10; + // int i=0; + while ((count = inputStream.read(zipBytes, 0, BUFFER_SIZE)) != -1) + { + if (status != null) + { + // Our status will be in 10% increments + if (count >= incrementSize * (lastTenth)) + status.display("Downloading zip file " + zipTarget.getName(), 1, count / 10, + incrementSize); + + // can't just increment because we maybe skip/hit 1/10ths due to + // faster/slower transfer rates, traffic, etc. + lastTenth = (int) Math.floor(((double) count / fileSize) * 10); + } + outputStream.write(zipBytes, 0, count); + } + + outputStream.close(); + inputStream.close(); + + if (extractWhenComplete) + extractZipFile(zipTarget); + + synchronized (this) + { + downloadDone = true; + } + } + + public BufferedInputStream getInputStream(File zipTarget) throws Exception + { + URLConnection urlConnection; + + if (zipTarget.isDirectory()) + { + + throw new Exception("ZipDownload: write exception! Can't write to directory!"); + } + + if (zipSource.isFile()) + { + inputStream = new FileInputStream(zipSource.file()); + + } + // In case the purl was constructed with a local file used as a URL + // TODO find the source of these bad constructions! (only applicabale when cF is launched as an + // application) + else if (zipSource.toString().startsWith("file://")) + { + try + { + File fileInput = new File(zipSource.toString().substring(7, zipSource.toString().length())); + inputStream = new FileInputStream(fileInput); + } + catch (Exception e) + { + System.out.println("ZipDownload: error reading local file"); + e.printStackTrace(); + throw new Exception("ZipDownload: IOException"); + } + } + else + { + urlConnection = zipSource.url().openConnection(); + if ((urlConnection == null) || aborted) + { + System.err.println("Cant open URLConnection for " + aborted + " " + zipSource); + throw new Exception("ZipDownload: IOException"); + } + try + { + urlConnection.connect(); + fileSize = urlConnection.getContentLength(); + inputStream = urlConnection.getInputStream(); + } + catch (FileNotFoundException e) + { + System.err.println("FileNotFound!"); + throw new Exception("ZipDownload: IOException"); + } + } + if ((inputStream == null) || aborted) + { + System.err.println("Cant open InputStream for " + aborted + " " + zipSource); + throw new Exception("ZipDownload: IOException"); + } + + return new BufferedInputStream(inputStream); + } + + public boolean isDownloadDone() + { + return downloadDone; + } + + @Override + public void handleIoError(Throwable e) + { + aborted = true; + NetTools.close(inputStream); + } + + @Override + public String toString() + { + return "ZipDownload() " + zipSource + " -> " + zipTarget; + } + + @Override + public void callback(Object o) + { + System.out.println("ZipDownload delivered: " + (o)); + } + + /** + * Convenience function to allow downloading and uncompressing of a zip file from a source to a + * target location with minimal effort. + * + * @param sourceZip + * The location of the zip file to download and uncompress. + * @param targetDir + * The location where the zip file should be uncompressed. This directory structure will + * be created if it doesn't exist. + * @param status + * The StatusReporter object that provides a source of state change visiblity; can be + * null. + * @param unCompress + * true if the file is a zip that needs to be uncompressed after download. + * @return TODO + */ + public static ZipDownload downloadAndPerhapsUncompress(ParsedURL sourceZip, File targetDir, + StatusReporter status, boolean unCompress) + { + // Create the target parent directory. + if (!targetDir.exists()) + targetDir.mkdirs(); + + println("downloading from zip URL: " + sourceZip + "\n\t to " + targetDir); + try + { + // FIXME make this use a (fixed?!) version of ParsedURL.isFile() ... + // if (sourceZip.toString().startsWith("file://")) + if (sourceZip.isFile()) + { + // copy zip file from assets source to cache + File sourceZipFile = sourceZip.file(); + String fileName = sourceZipFile.getName(); + File destFile = Files.newFile(targetDir, fileName); + File destFileDir = Files.newFile(targetDir, + destFile.toString().substring(0, destFile.toString().length() - 4)); + + println("Checking if dir exists: " + destFileDir.toString()); + + // Delete the previous directory if it exists. + if (destFileDir.exists()) + Files.deleteDirectory(destFileDir); + + StreamUtils.copyFile(sourceZipFile, destFile); + extractZipFile(sourceZipFile, targetDir); + + return null; + } + else + { + String fileName = sourceZip.getName(); + ZipDownload zipDownload = new ZipDownload(sourceZip, Files.newFile(targetDir, fileName), + status); + zipDownload.downloadAndWrite(unCompress); + return zipDownload; + } + } + catch (IOException e) + { + System.err.println("Error, zip file not found on the server!"); + // hiding stack trace -- it's annoying. + // e.printStackTrace(); + return null; + } + } + + /** + * Extracts a zip file into the directory where it resides + * + * @param zipSourcePath + * The path to the source zip file to extract. + */ + public static void extractZipFile(String zipSourcePath) throws IOException + { + extractZipFile(new File(zipSourcePath)); + } + + public static void extractZipFile(File zipSource) throws IOException + { + extractZipFile(zipSource, zipSource.getParentFile()); + } + + /** + * Extracts a zip file into the directory where it resides + * + * @param zipSourcePath + * The source zip file to extract + */ + public static void extractZipFile(String zipSourcePath, File unzipPath) throws IOException + { + extractZipFile(new File(zipSourcePath), unzipPath); + } + + /** + * Extracts a zip file into the directory where it resides + * + * @param zipSource + * The source zip file to extract + */ + public static void extractZipFile(File zipSource, File unzipPath) throws IOException + { + ZipFile zipFile = new ZipFile(zipSource); + System.out.println("Extracting zip file: " + zipSource); + Enumeration entries = zipFile.entries(); + while (entries.hasMoreElements()) + { + ZipEntry entry = (ZipEntry) entries.nextElement(); + String entryName = entry.getName(); + if (entry.isDirectory()) + { + File entryDir = new File(unzipPath, entryName); + if (!entryDir.exists()) + entryDir.mkdirs(); + + continue; + } + // else (if !entry.ex) + File outFile = new File(unzipPath, entryName); + String dirPath = outFile.getParent(); + File dir = new File(dirPath); + if (!dir.exists()) + dir.mkdirs(); + StreamUtils.copyInputStream(zipFile.getInputStream(entry), new BufferedOutputStream( + new FileOutputStream(outFile))); + } + + zipFile.close(); + + System.out.println("Finished extracting Zip file to " + unzipPath); + } + + /** + * Call to notify the object that its download is completed; + * + */ + public synchronized void downloadDone() + { + notifyAll(); + } + + public void waitForDownload() + { + synchronized (this) + { + if (!downloadDone && !aborted) + { + try + { + wait(); + } + catch (InterruptedException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } + + public static void setDownloadProcessor(DownloadProcessor downloadProcessor) + { + ZipDownload.downloadProcessor = downloadProcessor; + } + + @Override + public boolean isRecycled() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public Site getSite() + { + // TODO Auto-generated method stub + return null; + } + + /** + * + * @return What to tell the user about what is being downloaded. + */ + @Override + public String message() + { + return "zip archive " + zipSource.toString(); + } + + @Override + public ParsedURL location() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public void recycle() + { + if (inputStream != null) + try + { + inputStream.close(); + } + catch (IOException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Default empty implementation; will be ignored for this type. + */ + @Override + public boolean isImage() + { + return false; + } + + @Override + public Site getDownloadSite() + { + return null; + } + + @Override + public ParsedURL getDownloadLocation() + { + return location(); + } + + @Override + public boolean isCached() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public DownloadableLogRecord getLogRecord() + { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/simplCore/src/ecologylab/io/package.html b/simplCore/src/ecologylab/io/package.html index ea7963a7..f1343ef4 100644 --- a/simplCore/src/ecologylab/io/package.html +++ b/simplCore/src/ecologylab/io/package.html @@ -1,3 +1,3 @@ - -Infrastructural classes that provide a more usable API for I/O. - + +Infrastructural classes that provide a more usable API for I/O. + diff --git a/simplCore/src/ecologylab/logging/AbstractLogger.java b/simplCore/src/ecologylab/logging/AbstractLogger.java deleted file mode 100644 index b380ea97..00000000 --- a/simplCore/src/ecologylab/logging/AbstractLogger.java +++ /dev/null @@ -1,58 +0,0 @@ -package ecologylab.logging; - -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * For convenience. - * - * @author quyin - * - */ -public abstract class AbstractLogger implements ILogger -{ - - protected static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z"); - - @Override - public void debug(String fmt, Object... args) - { - log(LogLevel.DEBUG, fmt, args); - } - - @Override - public void info(String fmt, Object... args) - { - log(LogLevel.INFO, fmt, args); - } - - @Override - public void warn(String fmt, Object... args) - { - log(LogLevel.WARNING, fmt, args); - } - - @Override - public void error(String fmt, Object... args) - { - log(LogLevel.ERROR, fmt, args); - } - - @Override - public void fatal(String fmt, Object... args) - { - log(LogLevel.FATAL, fmt, args); - } - - /** - * Utility method. - * - * @return The current date and time as a string. - */ - protected String now() - { - Date d = new Date(); - return sdf.format(d); - } - -} diff --git a/simplCore/src/ecologylab/logging/BasicLoggerNames.java b/simplCore/src/ecologylab/logging/BasicLoggerNames.java deleted file mode 100644 index f64eeeef..00000000 --- a/simplCore/src/ecologylab/logging/BasicLoggerNames.java +++ /dev/null @@ -1,31 +0,0 @@ -package ecologylab.logging; - -//import org.apache.log4j.NDC; -//import org.apache.log4j.PropertyConfigurator; - -public class BasicLoggerNames { - - //can later be divided into fundamental, semantics and so on. - public static String baseLogger = "BaseLogger"; - - public static String htmlCacheLogger = "HTMLCacheLogger"; - - public static String metadataCacheLogger = "MetadataCacheLogger"; -// -// private static String configurationFile = "/log4j.configuration"; -// -// static { -// PropertyConfigurator.configure(BaseLogger.class -// .getResourceAsStream(configurationFile)); -// } -// -// public static void pushContext(String arg) -// { -// NDC.push(arg); -// } -// -// public static void removeContext() -// { -// NDC.remove(); -// } -} diff --git a/simplCore/src/ecologylab/logging/ILogger.java b/simplCore/src/ecologylab/logging/ILogger.java deleted file mode 100644 index fb4ddf5f..00000000 --- a/simplCore/src/ecologylab/logging/ILogger.java +++ /dev/null @@ -1,24 +0,0 @@ -package ecologylab.logging; - -/** - * A simple logger interface. - * - * @author quyin - * - */ -public interface ILogger -{ - - void debug(String fmt, Object... args); - - void info(String fmt, Object... args); - - void warn(String fmt, Object... args); - - void error(String fmt, Object... args); - - void fatal(String fmt, Object... args); - - void log(LogLevel level, String fmt, Object... args); - -} diff --git a/simplCore/src/ecologylab/logging/ILoggerFactory.java b/simplCore/src/ecologylab/logging/ILoggerFactory.java deleted file mode 100644 index 69ce759a..00000000 --- a/simplCore/src/ecologylab/logging/ILoggerFactory.java +++ /dev/null @@ -1,17 +0,0 @@ -package ecologylab.logging; - - -/** - * A simple logger factory interface. - * - * @author quyin - * - */ -public interface ILoggerFactory -{ - - ILogger getLogger(String name); - - ILogger getLogger(Class clazz); - -} diff --git a/simplCore/src/ecologylab/logging/LogEvent.java b/simplCore/src/ecologylab/logging/LogEvent.java new file mode 100644 index 00000000..9b3b8a50 --- /dev/null +++ b/simplCore/src/ecologylab/logging/LogEvent.java @@ -0,0 +1,110 @@ +package ecologylab.logging; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * The base class for logging events. + * + * @author quyin + */ +public class LogEvent +{ + + static SimpleDateFormat dateFormat; + + static + { + dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'Z"); + dateFormat.setTimeZone(TimeZone.getTimeZone("CST")); + } + + @simpl_scalar + private long timestamp; + + @simpl_scalar + private String time; + + @simpl_scalar + private String app; + + @simpl_scalar + private String username; + + @simpl_scalar + private String hashKey; + + public LogEvent() + { + // Default constructor must be empty, for deserialization. + } + + /** + * @return Timestamp of this event. + */ + public long getTimestamp() + { + return timestamp; + } + + public void setTimestamp(long timestamp) + { + this.timestamp = timestamp; + time = dateFormat.format(new Date(timestamp)); + } + + /** + * @return A human readable string for the timestamp of this event. + */ + public String getReadableTime() + { + if (time == null) + { + time = dateFormat.format(new Date(timestamp)); + } + return time; + } + + /** + * @return The app that generates this event. + */ + public String getApp() + { + return app; + } + + public void setApp(String app) + { + this.app = app; + } + + /** + * @return The username associated with this event. + */ + public String getUsername() + { + return username; + } + + public void setUsername(String username) + { + this.username = username; + } + + /** + * @return The hash key associated with this event. + */ + public String getHashKey() + { + return hashKey; + } + + public void setHashKey(String hashKey) + { + this.hashKey = hashKey; + } + +} diff --git a/simplCore/src/ecologylab/logging/LogEventTypeScope.java b/simplCore/src/ecologylab/logging/LogEventTypeScope.java new file mode 100644 index 00000000..e5e3e712 --- /dev/null +++ b/simplCore/src/ecologylab/logging/LogEventTypeScope.java @@ -0,0 +1,38 @@ +package ecologylab.logging; + +import ecologylab.serialization.SimplTypesScope; + +/** + * Type scope for log events + * + * @author quyin + */ +@SuppressWarnings("rawtypes") +public class LogEventTypeScope +{ + + public static final String NAME = "logging_events_translations"; + + private static Class[] classes = { + LogEvent.class, + LogPost.class, + }; + + private static SimplTypesScope scope; + + static + { + scope = SimplTypesScope.get(NAME, classes); + } + + public static SimplTypesScope get() + { + return scope; + } + + public static void addEventClass(Class eventClass) + { + scope.addTranslation(eventClass); + } + +} diff --git a/simplCore/src/ecologylab/logging/LogLevel.java b/simplCore/src/ecologylab/logging/LogLevel.java deleted file mode 100644 index d9cb252b..00000000 --- a/simplCore/src/ecologylab/logging/LogLevel.java +++ /dev/null @@ -1,12 +0,0 @@ -package ecologylab.logging; - -/** - * Basic levels for logging. - * - * @author quyin - * - */ -public enum LogLevel -{ - DEBUG, INFO, WARNING, ERROR, FATAL -} diff --git a/simplCore/src/ecologylab/logging/LogPost.java b/simplCore/src/ecologylab/logging/LogPost.java new file mode 100644 index 00000000..146d3617 --- /dev/null +++ b/simplCore/src/ecologylab/logging/LogPost.java @@ -0,0 +1,118 @@ +package ecologylab.logging; + +import java.util.ArrayList; +import java.util.List; + +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_scope; + +/** + * A list of log events that share common app / username / hashkey. + * + * It is thread safe to add events from multiple threads. + * + * @author quyin + */ +public class LogPost +{ + + @simpl_scalar + private String app; + + @simpl_scalar + private String username; + + @simpl_scalar + private String hashKey; + + @simpl_collection + @simpl_scope(LogEventTypeScope.NAME) + private List events; + + public LogPost() + { + // Default constructor must be empty, for deserialization. + } + + public String getApp() + { + return app; + } + + public void setApp(String app) + { + this.app = app; + } + + public String getUsername() + { + return username; + } + + public void setUsername(String username) + { + this.username = username; + } + + public String getHashKey() + { + return hashKey; + } + + public void setHashKey(String hashKey) + { + this.hashKey = hashKey; + } + + public List getEvents() + { + return events; + } + + public void addEvent(LogEvent event) + { + if (events == null) + { + synchronized (this) + { + if (events == null) + { + events = new ArrayList(); + } + } + } + + synchronized (events) + { + events.add(event); + } + } + + public void addEventNow(LogEvent event) + { + event.setTimestamp(System.currentTimeMillis()); + addEvent(event); + } + + public void addEvents(LogPost logPost) + { + if (logPost != null) + { + List eventsToAdd = logPost.getEvents(); + addEvents(eventsToAdd); + } + } + + public void addEvents(List eventsToAdd) + { + if (eventsToAdd != null) + { + for (LogEvent eventToAdd : eventsToAdd) + { + addEvent(eventToAdd); + } + } + } + +} diff --git a/simplCore/src/ecologylab/logging/SimpleLogger.java b/simplCore/src/ecologylab/logging/SimpleLogger.java deleted file mode 100644 index 284c357c..00000000 --- a/simplCore/src/ecologylab/logging/SimpleLogger.java +++ /dev/null @@ -1,37 +0,0 @@ -package ecologylab.logging; - -/** - * A basic logger that logs to console output. - * - * @author quyin - * - */ -public class SimpleLogger extends AbstractLogger -{ - - String name; - - SimpleLogger(String name) - { - this.name = name; - } - - @Override - public void log(LogLevel level, String fmt, Object... args) - { - String msg = String.format(fmt, args); - switch (level) - { - case DEBUG: - case INFO: - System.out.format("%s\t%s\t%s", now(), name, msg); - break; - case WARNING: - case ERROR: - case FATAL: - System.err.format("%s\t%s\t%s", now(), name, msg); - break; - } - } - -} diff --git a/simplCore/src/ecologylab/logging/SimpleLoggerFactory.java b/simplCore/src/ecologylab/logging/SimpleLoggerFactory.java deleted file mode 100644 index c94d5fbc..00000000 --- a/simplCore/src/ecologylab/logging/SimpleLoggerFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -package ecologylab.logging; - -/** - * A factory that produces BasicLoggers. - * - * @author quyin - * - */ -public class SimpleLoggerFactory implements ILoggerFactory -{ - - @Override - public ILogger getLogger(String name) - { - return new SimpleLogger(name); - } - - @Override - public ILogger getLogger(Class clazz) - { - return getLogger(clazz.getName()); - } - -} diff --git a/simplCore/src/ecologylab/net/ConnectionAdapter.java b/simplCore/src/ecologylab/net/ConnectionAdapter.java index 4ecd2335..781bb7d6 100644 --- a/simplCore/src/ecologylab/net/ConnectionAdapter.java +++ b/simplCore/src/ecologylab/net/ConnectionAdapter.java @@ -1,70 +1,70 @@ -package ecologylab.net; - -import java.io.File; -import java.net.URL; - -import ecologylab.generic.Debug; - -/** - * Adapter class to make it easier to use ParsedURL.connect(). - * The only method that you need to implement is - * parseFilesWithSuffix(String suffix). - * - * @author andruid - */ -public class ConnectionAdapter extends Debug -implements ConnectionHelper -{ - /** - * When this method is called, you know the file is a directory. - * This implementation does nothing. - * connect() will return null in this special case. - * - * @param file - */ - @Override - public void handleFileDirectory(File file) - { - } - - /** - * Used to provid status feedback to the user. - * The default implementation prints the message to the console. - * - * @param message - */ - @Override - public void displayStatus(String message) - { - println(message); - } - - /** - * Shuffle referential models when a redirect is observed, if you like. - * The default implementation allows all re-directs and keeps track of nothing. - * - * @param connectionURL - * - * @return true if the redirect is o.k., and we should continue processing the connect(). - * false if the redirect is unacceptable, and we should terminate processing. - */ - @Override - public boolean processRedirect(URL connectionURL) - { - return true; - } - - /** - * Tells the connect() method that it should go ahead and create a PURLConnection - * for all files that it finds. - * - * @param suffix - * @return true - */ - @Override - public boolean parseFilesWithSuffix(String suffix) - { - return true; - } - -} +package ecologylab.net; + +import java.io.File; +import java.net.URL; + +import ecologylab.generic.Debug; + +/** + * Adapter class to make it easier to use ParsedURL.connect(). + * The only method that you need to implement is + * parseFilesWithSuffix(String suffix). + * + * @author andruid + */ +public class ConnectionAdapter extends Debug +implements ConnectionHelper +{ + /** + * When this method is called, you know the file is a directory. + * This implementation does nothing. + * connect() will return null in this special case. + * + * @param file + */ + @Override + public void handleFileDirectory(File file) + { + } + + /** + * Used to provid status feedback to the user. + * The default implementation prints the message to the console. + * + * @param message + */ + @Override + public void displayStatus(String message) + { + println(message); + } + + /** + * Shuffle referential models when a redirect is observed, if you like. + * The default implementation allows all re-directs and keeps track of nothing. + * + * @param connectionURL + * + * @return true if the redirect is o.k., and we should continue processing the connect(). + * false if the redirect is unacceptable, and we should terminate processing. + */ + @Override + public boolean processRedirect(URL connectionURL) + { + return true; + } + + /** + * Tells the connect() method that it should go ahead and create a PURLConnection + * for all files that it finds. + * + * @param suffix + * @return true + */ + @Override + public boolean parseFilesWithSuffix(String suffix) + { + return true; + } + +} diff --git a/simplCore/src/ecologylab/net/ConnectionHelper.java b/simplCore/src/ecologylab/net/ConnectionHelper.java index b14015ac..510b017f 100644 --- a/simplCore/src/ecologylab/net/ConnectionHelper.java +++ b/simplCore/src/ecologylab/net/ConnectionHelper.java @@ -1,30 +1,30 @@ -package ecologylab.net; - -import java.io.File; - -/** - * Provides callbacks during {@link ecologylab.net.ParsedURL#connect(ConnectionHelper) ParsedURL.connect}, - * to enable filtering and custom processing as the connect operation unfolds. - * - * @author andruid - */ -public interface ConnectionHelper extends ConnectionHelperJustRemote -{ - /** - * When this method is called, you know the file is a directory. - * Process it if you wish. - * connect() will return null in this special case. - * - * @param file - */ - public void handleFileDirectory(File file); - /** - * Tells the connect() method that it should go ahead and create a PURLConnection - * for files that have this suffix. - * - * @param suffix - * @return true if files with this suffix should be parsed; false if they should be ignored. - */ - public boolean parseFilesWithSuffix(String suffix); - -} +package ecologylab.net; + +import java.io.File; + +/** + * Provides callbacks during {@link ecologylab.net.ParsedURL#connect(ConnectionHelper) ParsedURL.connect}, + * to enable filtering and custom processing as the connect operation unfolds. + * + * @author andruid + */ +public interface ConnectionHelper extends ConnectionHelperJustRemote +{ + /** + * When this method is called, you know the file is a directory. + * Process it if you wish. + * connect() will return null in this special case. + * + * @param file + */ + public void handleFileDirectory(File file); + /** + * Tells the connect() method that it should go ahead and create a PURLConnection + * for files that have this suffix. + * + * @param suffix + * @return true if files with this suffix should be parsed; false if they should be ignored. + */ + public boolean parseFilesWithSuffix(String suffix); + +} diff --git a/simplCore/src/ecologylab/net/NetTools.java b/simplCore/src/ecologylab/net/NetTools.java index da23e406..ae09742f 100644 --- a/simplCore/src/ecologylab/net/NetTools.java +++ b/simplCore/src/ecologylab/net/NetTools.java @@ -1,223 +1,223 @@ -package ecologylab.net; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.URLConnection; -import java.net.UnknownHostException; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; - -import ecologylab.collections.CollectionTools; -import ecologylab.generic.Debug; - -/** - * Reusable static methods that do nifty network stuff. - * - * @author andruid - * @author blake - * @author eunyee - * - */ -public class NetTools extends Debug -{ - final static String SUPPORTED_CHARSETS[] = - { "latin1", "us-ascii", "windows-1250", - "windows-1251", "windows-1252", "windows-1253", "windows-1254", "windows-1257", "iso-8859-1", - "iso-8859-2", "iso-8859-4", "iso-8859-5", "iso-8859-7", "iso-8859-9", "iso-8859-13", - "iso-8859-15", "ISO-8859-1", "ISO_8859-1", "ISO-8859-2", "ISO-8859-4", "ISO-8859-5", - "ISO-8859-7", "ISO-8859-9", "ISO-8859-13", "ISO-8859-15", "koi8-r", "utf-8", "utf-16", - "utf-16be", "utf-16le", "UTF-8", "UTF-16", "UTF-16be", "UTF-16le" }; - - final static HashMap supportedCharsetMap = CollectionTools.buildHashMapFromStrings(SUPPORTED_CHARSETS); - - /** - * Seek a charset specification in the MimeType header of the HTTP request. The return values are - * strange, in order to enable reporting an error to happen conveniently around the call site. - * - * @param mimeType - * The Mime Type header. - * - * @return Null if the charset is supported (including if there is no specificaton of it in the - * header). The charset that is unsupported, if that is the case. - */ - public static String isCharsetSupported(String mimeType) - { - if (mimeType == null) - return null; - - int charsetIndex = mimeType.indexOf("charset"); - if (charsetIndex > -1) - { - int equalsIndex = mimeType.indexOf('=', charsetIndex); - if (equalsIndex++ > -1) // seek and skip over the equals - { - int closingSemIndex = mimeType.indexOf(';', equalsIndex); - String charset = null; - if (equalsIndex >= closingSemIndex) - { - charset = (closingSemIndex == -1) ? mimeType.substring(equalsIndex) - : mimeType.substring(closingSemIndex, equalsIndex); - } - - if ((charset != null) && (charset.length() > 0)) - { - charset = charset.trim(); - if (charset.startsWith("\"")) - charset = charset.substring(1); - if (charset.endsWith("\"")) - charset = charset.substring(0, charset.length() - 1); - // println("CHARSET: '" + charset + "'"); - if (!supportedCharsetMap.containsKey(charset)) - { - return charset; - } - } - } - } - return null; - /* - * StringTokenizer st = new StringTokenizer( mimeType, ";= "); String encoding = null; - * while(st.hasMoreTokens()) { if( st.nextToken().equals("charset")) { encoding = - * st.nextToken(); println("ENCODING : " + encoding); } } if( (encoding != null) && - * !supportedCharsetMap.containsKey(encoding) ) { - * infoCollector.displayStatus("Cant process charset " + encoding + " in " + purl.toString() ); - * return null; } - */ - } - - /** - * Free resources as possible on the URLConnection passed in. - * - * This is accomplished by calling disconnect() if it turns out to be an instance of - * HttpURLConnection. - * - * @param urlConnection - * a reference to a URLConnection. - */ - public static void disconnect(URLConnection urlConnection) - { - if ((urlConnection != null) && (urlConnection instanceof HttpURLConnection)) - { - HttpURLConnection httpConnection = (HttpURLConnection) urlConnection; - httpConnection.disconnect(); // free resources! - } - } - - public static void close(InputStream inStream) - { - if (inStream != null) - try - { - inStream.close(); - } - catch (IOException e) - { - } - } - - static String localHost = null; - - /** - * local host address (parse out only IP address) - * - * @return - */ - public static String localHost() - { - String localHost1 = NetTools.localHost; - if (localHost1 == null) - { - try - { - localHost1 = InetAddress.getLocalHost().toString(); - // localHost = localHost.replace('/','_'); - localHost1 = localHost1.substring(localHost1.indexOf('/') + 1); - NetTools.localHost = localHost1; - } - catch (UnknownHostException e) - { - e.printStackTrace(); - } - } - return localHost1; - } - - public static InetAddress[] getAllInetAddressesForLocalhost() - { - HashSet addresses = new HashSet(); - - try - { - Enumeration byName = NetworkInterface.getNetworkInterfaces(); - while (byName.hasMoreElements()) - { - NetworkInterface nextElement = byName.nextElement(); - // System.out.println(nextElement.getDisplayName()); - Enumeration inetAddresses = nextElement.getInetAddresses(); - while (inetAddresses.hasMoreElements()) - { - addresses.add(inetAddresses.nextElement()); - } - } - } - catch (SocketException e1) - { - e1.printStackTrace(); - } - try - { - for (InetAddress a : InetAddress.getAllByName("localhost")) - { - addresses.add(a); - } - } - catch (UnknownHostException e) - { - e.printStackTrace(); - } - - try - { - for (InetAddress a : InetAddress.getAllByName(InetAddress.getLocalHost().getHostAddress())) - { - addresses.add(a); - } - } - catch (UnknownHostException e) - { - e.printStackTrace(); - } - - try - { - addresses.add(InetAddress.getLocalHost()); - } - catch (UnknownHostException e) - { - e.printStackTrace(); - } - - return addresses.toArray(new InetAddress[addresses.size()]); - } - - /** - * Convenience method for getting a single-element array of InetAddresses for servers that - * normally take an array, but when only one is available. - * - * @param address - * the address to wrap. - * @return a single-element array containing address. - */ - public static final InetAddress[] wrapSingleAddress(InetAddress address) - { - InetAddress[] wrappedAddress = - { address }; - - return wrappedAddress; - } -} +package ecologylab.net; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.URLConnection; +import java.net.UnknownHostException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; + +import ecologylab.collections.CollectionTools; +import ecologylab.generic.Debug; + +/** + * Reusable static methods that do nifty network stuff. + * + * @author andruid + * @author blake + * @author eunyee + * + */ +public class NetTools extends Debug +{ + final static String SUPPORTED_CHARSETS[] = + { "latin1", "us-ascii", "windows-1250", + "windows-1251", "windows-1252", "windows-1253", "windows-1254", "windows-1257", "iso-8859-1", + "iso-8859-2", "iso-8859-4", "iso-8859-5", "iso-8859-7", "iso-8859-9", "iso-8859-13", + "iso-8859-15", "ISO-8859-1", "ISO_8859-1", "ISO-8859-2", "ISO-8859-4", "ISO-8859-5", + "ISO-8859-7", "ISO-8859-9", "ISO-8859-13", "ISO-8859-15", "koi8-r", "utf-8", "utf-16", + "utf-16be", "utf-16le", "UTF-8", "UTF-16", "UTF-16be", "UTF-16le" }; + + final static HashMap supportedCharsetMap = CollectionTools.buildHashMapFromStrings(SUPPORTED_CHARSETS); + + /** + * Seek a charset specification in the MimeType header of the HTTP request. The return values are + * strange, in order to enable reporting an error to happen conveniently around the call site. + * + * @param mimeType + * The Mime Type header. + * + * @return Null if the charset is supported (including if there is no specificaton of it in the + * header). The charset that is unsupported, if that is the case. + */ + public static String isCharsetSupported(String mimeType) + { + if (mimeType == null) + return null; + + int charsetIndex = mimeType.indexOf("charset"); + if (charsetIndex > -1) + { + int equalsIndex = mimeType.indexOf('=', charsetIndex); + if (equalsIndex++ > -1) // seek and skip over the equals + { + int closingSemIndex = mimeType.indexOf(';', equalsIndex); + String charset = null; + if (equalsIndex >= closingSemIndex) + { + charset = (closingSemIndex == -1) ? mimeType.substring(equalsIndex) + : mimeType.substring(closingSemIndex, equalsIndex); + } + + if ((charset != null) && (charset.length() > 0)) + { + charset = charset.trim(); + if (charset.startsWith("\"")) + charset = charset.substring(1); + if (charset.endsWith("\"")) + charset = charset.substring(0, charset.length() - 1); + // println("CHARSET: '" + charset + "'"); + if (!supportedCharsetMap.containsKey(charset)) + { + return charset; + } + } + } + } + return null; + /* + * StringTokenizer st = new StringTokenizer( mimeType, ";= "); String encoding = null; + * while(st.hasMoreTokens()) { if( st.nextToken().equals("charset")) { encoding = + * st.nextToken(); println("ENCODING : " + encoding); } } if( (encoding != null) && + * !supportedCharsetMap.containsKey(encoding) ) { + * infoCollector.displayStatus("Cant process charset " + encoding + " in " + purl.toString() ); + * return null; } + */ + } + + /** + * Free resources as possible on the URLConnection passed in. + * + * This is accomplished by calling disconnect() if it turns out to be an instance of + * HttpURLConnection. + * + * @param urlConnection + * a reference to a URLConnection. + */ + public static void disconnect(URLConnection urlConnection) + { + if ((urlConnection != null) && (urlConnection instanceof HttpURLConnection)) + { + HttpURLConnection httpConnection = (HttpURLConnection) urlConnection; + httpConnection.disconnect(); // free resources! + } + } + + public static void close(InputStream inStream) + { + if (inStream != null) + try + { + inStream.close(); + } + catch (IOException e) + { + } + } + + static String localHost = null; + + /** + * local host address (parse out only IP address) + * + * @return + */ + public static String localHost() + { + String localHost1 = NetTools.localHost; + if (localHost1 == null) + { + try + { + localHost1 = InetAddress.getLocalHost().toString(); + // localHost = localHost.replace('/','_'); + localHost1 = localHost1.substring(localHost1.indexOf('/') + 1); + NetTools.localHost = localHost1; + } + catch (UnknownHostException e) + { + e.printStackTrace(); + } + } + return localHost1; + } + + public static InetAddress[] getAllInetAddressesForLocalhost() + { + HashSet addresses = new HashSet(); + + try + { + Enumeration byName = NetworkInterface.getNetworkInterfaces(); + while (byName.hasMoreElements()) + { + NetworkInterface nextElement = byName.nextElement(); + // System.out.println(nextElement.getDisplayName()); + Enumeration inetAddresses = nextElement.getInetAddresses(); + while (inetAddresses.hasMoreElements()) + { + addresses.add(inetAddresses.nextElement()); + } + } + } + catch (SocketException e1) + { + e1.printStackTrace(); + } + try + { + for (InetAddress a : InetAddress.getAllByName("localhost")) + { + addresses.add(a); + } + } + catch (UnknownHostException e) + { + e.printStackTrace(); + } + + try + { + for (InetAddress a : InetAddress.getAllByName(InetAddress.getLocalHost().getHostAddress())) + { + addresses.add(a); + } + } + catch (UnknownHostException e) + { + e.printStackTrace(); + } + + try + { + addresses.add(InetAddress.getLocalHost()); + } + catch (UnknownHostException e) + { + e.printStackTrace(); + } + + return addresses.toArray(new InetAddress[addresses.size()]); + } + + /** + * Convenience method for getting a single-element array of InetAddresses for servers that + * normally take an array, but when only one is available. + * + * @param address + * the address to wrap. + * @return a single-element array containing address. + */ + public static final InetAddress[] wrapSingleAddress(InetAddress address) + { + InetAddress[] wrappedAddress = + { address }; + + return wrappedAddress; + } +} diff --git a/simplCore/src/ecologylab/net/PURLConnection.java b/simplCore/src/ecologylab/net/PURLConnection.java index ee8e2ad9..69de1bb9 100644 --- a/simplCore/src/ecologylab/net/PURLConnection.java +++ b/simplCore/src/ecologylab/net/PURLConnection.java @@ -1,353 +1,353 @@ -package ecologylab.net; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.net.URLConnection; -import java.util.HashMap; - -import ecologylab.collections.CollectionTools; -import ecologylab.generic.Debug; - -/** - * Combines URLConnection with InputStream, providing convenience. - * - * @author andruid - */ -public class PURLConnection extends Debug -{ - protected ParsedURL purl; - protected InputStream inputStream; - protected HttpURLConnection urlConnection; - protected String mimeType; - - /** - * If true, a timeout occurred during connect(). - */ - boolean timeout = false; - - boolean good = false; - - /** Fill out the instance of this resulting from a succcessful connect(). - * @param purl TODO - * @param urlConnection - * @param inputStream - */ - public PURLConnection(ParsedURL purl) - { - this.purl = purl; - } - public PURLConnection(ParsedURL purl, HttpURLConnection urlConnection, InputStream inputStream) - { - this.purl = purl; - this.inputStream = inputStream; - this.urlConnection = urlConnection; - this.good = true; - } - - public void connect(ConnectionHelper connectionHelper, String userAgent, - int connectionTimeout, int readTimeout) - { - // get an InputStream, and set the mimeType, if not bad - if (purl.isFile()) - { - File file = purl.file(); - if (file.isDirectory()) - connectionHelper.handleFileDirectory(file); - else - { - String suffix = purl.suffix(); - if (suffix != null) - { - if (connectionHelper.parseFilesWithSuffix(suffix)) - { - try - { - fileConnect(); - } - catch (FileNotFoundException e) - { - error("Can't open because FileNotFoundException"); - } - } - } - } - } - else - { - networkConnectAndCatch(connectionHelper, userAgent, connectionTimeout, readTimeout); - } - } - public void fileConnect() throws FileNotFoundException - { - inputStream = new FileInputStream(purl.file()); - good = true; - } - - public void streamConnect(InputStream inputStream) - { - this.inputStream = inputStream; - good = true; - } - - public void networkConnectAndCatch(ConnectionHelper connectionHelper, String userAgent) - { - networkConnectAndCatch(connectionHelper, userAgent, ParsedURL.CONNECT_TIMEOUT, ParsedURL.READ_TIMEOUT); - } - /** - * @param connectionHelper - * @param userAgent - * @param connectionTimeout - * @param readTimeout - */ - public void networkConnectAndCatch(ConnectionHelper connectionHelper, String userAgent, - int connectionTimeout, int readTimeout) - { - try - { - networkConnect(connectionHelper, userAgent, connectionTimeout, readTimeout); - } - catch (SocketTimeoutException e) - { - timeout = true; - cleanup(e); - } - catch (FileNotFoundException e) - { - cleanup(e); - } - catch (IOException e) - { - cleanup(e); - } - catch (Exception e) // catch all exceptions, including security - { - cleanup(e); - } - } - public void networkConnect(ConnectionHelperJustRemote connectionHelper, String userAgent) - throws IOException - { - networkConnect(connectionHelper, userAgent, ParsedURL.CONNECT_TIMEOUT, ParsedURL.READ_TIMEOUT); - } - /** - * @param connectionHelper - * @param userAgent - * @param connectionTimeout - * @param readTimeout - * @throws IOException - * @throws Exception - */ - public void networkConnect(ConnectionHelperJustRemote connectionHelper, String userAgent, - int connectionTimeout, int readTimeout) - throws IOException - { - URL url = purl.url(); - urlConnection = (HttpURLConnection) url.openConnection(); - - // hack so google thinks we're a normal browser - // (otherwise, it wont serve us) - // connection.setRequestProperty("user-agent", GOOGLE_BOT_USER_AGENT_0); - urlConnection.setRequestProperty("user-agent", userAgent); - - // Set the connection and read timeout. - urlConnection.setConnectTimeout(connectionTimeout); - urlConnection.setReadTimeout(readTimeout); - - /* - * //TODO include more structure instead of this total hack! if - * ("nytimes.com".equals(this.domain())) { String auth = new - * sun.misc.BASE64Encoder().encode("fred66:fred66".getBytes()); - * connection.setRequestProperty("Authorization", auth); } - */ - urlConnection.getContentLength(); - String mimeType = urlConnection.getContentType(); - - // no one uses the encoding header: connection.getContentEncoding(); - String unsupportedCharset = NetTools.isCharsetSupported(mimeType); - if (unsupportedCharset != null) - { - String message = "Cant process charset " + unsupportedCharset + " in " - + this; - connectionHelper.displayStatus(message); - error(message); - } - else - { - // notice if url changed between request and retrieved connection - // if so, this is a server-side redirect - URL connectionURL = urlConnection.getURL(); - - if (!url.equals(connectionURL)) // follow redirects! - { - // avoid doubly stuffed urls - //TODO -- does this test belong here????? - String connectionFile = connectionURL.getFile(); - String file = url.getFile(); - - if ((file.indexOf("http://") == -1) && (connectionFile.indexOf("http://") == -1)) -// if ((path.indexOf("http://") != -1) || (connectionPath.indexOf("http://") != -1)) - { - if (connectionHelper.processRedirect(connectionURL)) - inputStream = urlConnection.getInputStream(); - this.good = true; - } - else - { - println("WEIRD: skipping double stuffed url: " + connectionURL); - } - } - else - { - // no redirect, eveything is kewl - inputStream = urlConnection.getInputStream(); - this.good = true; - } - } - } - - private void cleanup(Exception e) - { - error("connect() " + e); - close(); - } - - - public void recycle() - { - close(); -// purl.recycle(); -// purl = null; - } - public void reconnect() - { - if (purl != null && purl.isFile() && inputStream ==null) - { - try - { - inputStream = new FileInputStream(purl.file()); - } - catch (FileNotFoundException e) - { - e.printStackTrace(); - } - } - } - /** - * Close the InputStream, and disconnect the URLConnection. - */ - public void close() - { - // parsing done. now free resources asap to avert leaking and memory fragmentation - // (this is a known problem w java.net.HttpURLConnection) - InputStream inputStream = this.inputStream; - if (inputStream != null) - { - NetTools.close(inputStream); - this.inputStream = null; - } - if (urlConnection != null) - { - urlConnection.disconnect(); - this.urlConnection = null; - } - mimeType = null; - } - - /** - * @return Returns the inputStream. - */ - public InputStream inputStream() - { - return inputStream; - } - - /** - * @return Returns the urlConnection. - */ - public URLConnection urlConnection() - { - return urlConnection; - } - - /** - * Find the mime type returned by the web server to the URLConnection, in its header. - * Thus, if there is no URLConnection (as for local file system), this always returns null. - * - * @return the mime type or null - */ - public String mimeType() - { - String result = this.mimeType; - if ((result == null) && (urlConnection != null)) - { - result = urlConnection.getContentType(); - if (result != null) - { - // create the appropriate DocumentType object - // lookout for mime types with charset appened - int semicolonIndex = result.indexOf(';'); - if (semicolonIndex > 0) - result = result.substring(0, semicolonIndex); - this.mimeType = result; - } - } - return result; - } - - @Override - public String toString() - { - String u = urlConnection != null ? urlConnection.toString() : "null"; - String p = purl != null ? purl.toString() : "null"; - String f = purl != null ? (purl.file() != null ? "path: "+ purl.file().toString() + " exists: " + purl.file().exists(): "null file") : "null purl"; - StringBuilder sb = new StringBuilder(); - - sb.append("urlConnection: "); - sb.append(u); - sb.append("\t purl: "); - sb.append(p); - sb.append("\t file: "); - sb.append(f); - - return sb.toString(); - - } - - public ParsedURL getPurl() - { - return purl; - } - - static final String[] noAlphaMimeStrings = - { - "image/jpeg", "image/bmp", - }; - - static final HashMap noAlphaMimeMap = CollectionTools - .buildHashMapFromStrings(noAlphaMimeStrings); - - public boolean isNoAlpha() - { - return mimeType != null && noAlphaMimeMap.containsKey(mimeType); - } - - public boolean getTimeout() - { - return timeout; - } - - public boolean isGood() - { - return good; - } - - public void setMimeType(String mimeType) { - this.mimeType = mimeType; - } -} +package ecologylab.net; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashMap; + +import ecologylab.collections.CollectionTools; +import ecologylab.generic.Debug; + +/** + * Combines URLConnection with InputStream, providing convenience. + * + * @author andruid + */ +public class PURLConnection extends Debug +{ + protected ParsedURL purl; + protected InputStream inputStream; + protected HttpURLConnection urlConnection; + protected String mimeType; + + /** + * If true, a timeout occurred during connect(). + */ + boolean timeout = false; + + boolean good = false; + + /** Fill out the instance of this resulting from a succcessful connect(). + * @param purl TODO + * @param urlConnection + * @param inputStream + */ + public PURLConnection(ParsedURL purl) + { + this.purl = purl; + } + public PURLConnection(ParsedURL purl, HttpURLConnection urlConnection, InputStream inputStream) + { + this.purl = purl; + this.inputStream = inputStream; + this.urlConnection = urlConnection; + this.good = true; + } + + public void connect(ConnectionHelper connectionHelper, String userAgent, + int connectionTimeout, int readTimeout) + { + // get an InputStream, and set the mimeType, if not bad + if (purl.isFile()) + { + File file = purl.file(); + if (file.isDirectory()) + connectionHelper.handleFileDirectory(file); + else + { + String suffix = purl.suffix(); + if (suffix != null) + { + if (connectionHelper.parseFilesWithSuffix(suffix)) + { + try + { + fileConnect(); + } + catch (FileNotFoundException e) + { + error("Can't open because FileNotFoundException"); + } + } + } + } + } + else + { + networkConnectAndCatch(connectionHelper, userAgent, connectionTimeout, readTimeout); + } + } + public void fileConnect() throws FileNotFoundException + { + inputStream = new FileInputStream(purl.file()); + good = true; + } + + public void streamConnect(InputStream inputStream) + { + this.inputStream = inputStream; + good = true; + } + + public void networkConnectAndCatch(ConnectionHelper connectionHelper, String userAgent) + { + networkConnectAndCatch(connectionHelper, userAgent, ParsedURL.CONNECT_TIMEOUT, ParsedURL.READ_TIMEOUT); + } + /** + * @param connectionHelper + * @param userAgent + * @param connectionTimeout + * @param readTimeout + */ + public void networkConnectAndCatch(ConnectionHelper connectionHelper, String userAgent, + int connectionTimeout, int readTimeout) + { + try + { + networkConnect(connectionHelper, userAgent, connectionTimeout, readTimeout); + } + catch (SocketTimeoutException e) + { + timeout = true; + cleanup(e); + } + catch (FileNotFoundException e) + { + cleanup(e); + } + catch (IOException e) + { + cleanup(e); + } + catch (Exception e) // catch all exceptions, including security + { + cleanup(e); + } + } + public void networkConnect(ConnectionHelperJustRemote connectionHelper, String userAgent) + throws IOException + { + networkConnect(connectionHelper, userAgent, ParsedURL.CONNECT_TIMEOUT, ParsedURL.READ_TIMEOUT); + } + /** + * @param connectionHelper + * @param userAgent + * @param connectionTimeout + * @param readTimeout + * @throws IOException + * @throws Exception + */ + public void networkConnect(ConnectionHelperJustRemote connectionHelper, String userAgent, + int connectionTimeout, int readTimeout) + throws IOException + { + URL url = purl.url(); + urlConnection = (HttpURLConnection) url.openConnection(); + + // hack so google thinks we're a normal browser + // (otherwise, it wont serve us) + // connection.setRequestProperty("user-agent", GOOGLE_BOT_USER_AGENT_0); + urlConnection.setRequestProperty("user-agent", userAgent); + + // Set the connection and read timeout. + urlConnection.setConnectTimeout(connectionTimeout); + urlConnection.setReadTimeout(readTimeout); + + /* + * //TODO include more structure instead of this total hack! if + * ("nytimes.com".equals(this.domain())) { String auth = new + * sun.misc.BASE64Encoder().encode("fred66:fred66".getBytes()); + * connection.setRequestProperty("Authorization", auth); } + */ + urlConnection.getContentLength(); + String mimeType = urlConnection.getContentType(); + + // no one uses the encoding header: connection.getContentEncoding(); + String unsupportedCharset = NetTools.isCharsetSupported(mimeType); + if (unsupportedCharset != null) + { + String message = "Cant process charset " + unsupportedCharset + " in " + + this; + connectionHelper.displayStatus(message); + error(message); + } + else + { + // notice if url changed between request and retrieved connection + // if so, this is a server-side redirect + URL connectionURL = urlConnection.getURL(); + + if (!url.equals(connectionURL)) // follow redirects! + { + // avoid doubly stuffed urls + //TODO -- does this test belong here????? + String connectionFile = connectionURL.getFile(); + String file = url.getFile(); + + if ((file.indexOf("http://") == -1) && (connectionFile.indexOf("http://") == -1)) +// if ((path.indexOf("http://") != -1) || (connectionPath.indexOf("http://") != -1)) + { + if (connectionHelper.processRedirect(connectionURL)) + inputStream = urlConnection.getInputStream(); + this.good = true; + } + else + { + println("WEIRD: skipping double stuffed url: " + connectionURL); + } + } + else + { + // no redirect, eveything is kewl + inputStream = urlConnection.getInputStream(); + this.good = true; + } + } + } + + private void cleanup(Exception e) + { + error("connect() " + e); + close(); + } + + + public void recycle() + { + close(); +// purl.recycle(); +// purl = null; + } + public void reconnect() + { + if (purl != null && purl.isFile() && inputStream ==null) + { + try + { + inputStream = new FileInputStream(purl.file()); + } + catch (FileNotFoundException e) + { + e.printStackTrace(); + } + } + } + /** + * Close the InputStream, and disconnect the URLConnection. + */ + public void close() + { + // parsing done. now free resources asap to avert leaking and memory fragmentation + // (this is a known problem w java.net.HttpURLConnection) + InputStream inputStream = this.inputStream; + if (inputStream != null) + { + NetTools.close(inputStream); + this.inputStream = null; + } + if (urlConnection != null) + { + urlConnection.disconnect(); + this.urlConnection = null; + } + mimeType = null; + } + + /** + * @return Returns the inputStream. + */ + public InputStream inputStream() + { + return inputStream; + } + + /** + * @return Returns the urlConnection. + */ + public URLConnection urlConnection() + { + return urlConnection; + } + + /** + * Find the mime type returned by the web server to the URLConnection, in its header. + * Thus, if there is no URLConnection (as for local file system), this always returns null. + * + * @return the mime type or null + */ + public String mimeType() + { + String result = this.mimeType; + if ((result == null) && (urlConnection != null)) + { + result = urlConnection.getContentType(); + if (result != null) + { + // create the appropriate DocumentType object + // lookout for mime types with charset appened + int semicolonIndex = result.indexOf(';'); + if (semicolonIndex > 0) + result = result.substring(0, semicolonIndex); + this.mimeType = result; + } + } + return result; + } + + @Override + public String toString() + { + String u = urlConnection != null ? urlConnection.toString() : "null"; + String p = purl != null ? purl.toString() : "null"; + String f = purl != null ? (purl.file() != null ? "path: "+ purl.file().toString() + " exists: " + purl.file().exists(): "null file") : "null purl"; + StringBuilder sb = new StringBuilder(); + + sb.append("urlConnection: "); + sb.append(u); + sb.append("\t purl: "); + sb.append(p); + sb.append("\t file: "); + sb.append(f); + + return sb.toString(); + + } + + public ParsedURL getPurl() + { + return purl; + } + + static final String[] noAlphaMimeStrings = + { + "image/jpeg", "image/bmp", + }; + + static final HashMap noAlphaMimeMap = CollectionTools + .buildHashMapFromStrings(noAlphaMimeStrings); + + public boolean isNoAlpha() + { + return mimeType != null && noAlphaMimeMap.containsKey(mimeType); + } + + public boolean getTimeout() + { + return timeout; + } + + public boolean isGood() + { + return good; + } + + public void setMimeType(String mimeType) { + this.mimeType = mimeType; + } +} diff --git a/simplCore/src/ecologylab/net/ParsedURL.java b/simplCore/src/ecologylab/net/ParsedURL.java index 881d42d1..695de46f 100644 --- a/simplCore/src/ecologylab/net/ParsedURL.java +++ b/simplCore/src/ecologylab/net/ParsedURL.java @@ -1,1559 +1,1548 @@ -package ecologylab.net; - -import java.io.File; -import java.io.IOException; -import java.net.CookieHandler; -import java.net.CookieManager; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.net.URLEncoder; -import java.util.HashMap; -import java.util.StringTokenizer; - -import ecologylab.collections.CollectionTools; -import ecologylab.generic.Debug; -import ecologylab.generic.IntSlot; -import ecologylab.generic.StringTools; -import ecologylab.io.Files; -import ecologylab.platformspecifics.FundamentalPlatformSpecifics; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.Format; - -/** - * Extends the URL with many features for the convenience and power of network programmers. New - * class for manipulating and displaying URLs. - * - * Uses lazy evaluation to minimize storage allocation. - * - * @author andruid - * @author eunyee - * @author madhur - */ -public class ParsedURL extends Debug implements MimeType -{ - private static final String NOT_IN_THE_FORMAT_OF_A_WEB_ADDRESS = " is not in the format of a web address"; - - private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)"; - - /** - * this is the no hash url, that is, the one with # and anything after it stripped out. - */ - protected URL url = null; - - /** - * If this is built from an entity of the local file system, store a reference to the object for - * that here. - */ - File file; - - /** - * URL with hash, that is, a reference to an anchor within the document. - */ - protected URL hashUrl = null; - - /** - * Directory that the document referred to by the URL resides in. - */ - protected URL directory = null; - - private ParsedURL directoryPURL; - - /** - * String representation of the URL. - */ - protected String string = null; - - /** - * Shorter version of the string, for printing in tight spaces. - */ - String shortString; - - /* lower case of the url string */ - protected String lc = null; - - /* suffix string of the url */ - protected String suffix = null; - - /* domain value string of the ulr */ - protected String domain = null; - - protected boolean includePrefix = true; - - public static CookieManager cookieManager = new CookieManager(); - - static - { - //cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); - CookieHandler.setDefault(cookieManager); - } - - public ParsedURL(URL url) - { - String hash = url.getRef(); - - if ("file".equals(url.getProtocol())) - { - String urlString = url.toString(); - if (urlString.startsWith("file://")) // this should be the case... - { - this.file = new File(urlString.substring(7)); - } - else // if not, try our hardest to make a good file - { - this.file = new File(url.getHost()+url.getPath()); - } - this.url = url; - } - else if (hash == null) - { - this.url = url; - this.hashUrl = url; - } - else - { - this.hashUrl = url; - try - { - // form no hash url (toss hash) - this.url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile()); - } - catch (MalformedURLException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - - /** - * - * @return true if this refers to a file, and that file exists. Also true if this does not refer to a file. - */ - public boolean isNotFileOrExists() - { - return (file == null) || file.exists(); - } - - /** - * Create a ParsedURL from a file. If the file is a directory, append "/" to the path, so that - * relative URLs will be formed properly later. - * - * @param file - */ - public ParsedURL(File file) - { - try - { - String urlString = "file://" + file.getAbsolutePath(); - urlString = urlString.replace('\\', '/'); - if (file.isDirectory()) - urlString += "/"; - this.url = new URL(urlString); - } - catch (MalformedURLException e) - { - e.printStackTrace(); - } - this.file = file; - } - - /* - * Constructor with a url string parameter. get absolute URL with getAbsolute() method. - */ - /* - * public ParsedURL(String urlString) { // The second parameter of getAbolute method is error - * description. this.url = getAbsolute(urlString, "").url(); } - */ - // ///////////////////////////////////////////////////////////////////// - /** - * Create a PURL from an absolute address. (Do it the quick and dirty way, providing less error - * handling.) NB: Only call this method if you are *sure* a MalformedURlException would never be - * produced. - * - */ - public static ParsedURL getAbsolute(String webAddr) - { - return getAbsolute(webAddr, "getAbsolute(String) "); - } - - public static ParsedURL get(URI uri) - { - return getAbsolute(uri.toString()); - } - /** - * Create a PURL from an absolute address. - * - * @param webAddr - * url string - * @param errorDescriptor - * which will be printed out in the trace file if there is something happen converting - * from the url string to URL. - * @return ParsedURL from url string parameter named webAddr, or null if the param is malformed. - */ - public static ParsedURL getAbsolute(String webAddr, String errorDescriptor) - { - if (webAddr == null || webAddr.length() <= 7) - { - println("ERROR: ParsedURL.getAbsolute() webAddr is null or too short: [" + webAddr + "]"); - //Thread.dumpStack(); //We don't really need such a hostile message. - } - else - { - try - { - URL url = new URL(webAddr); - if (isUndetectedMalformedURL(url)) - return null; - return new ParsedURL(url); - } - catch (MalformedURLException e) - { - if (!"".equals(errorDescriptor)) - errorDescriptor = "\n" + errorDescriptor; - Debug.error(webAddr, NOT_IN_THE_FORMAT_OF_A_WEB_ADDRESS + "." + errorDescriptor); - } - } - return null; - } - - /** - * Determines a URL is malformed since Java fails to detect this. - * - * @param url - * @return - */ - private static boolean isUndetectedMalformedURL(URL url) - { - // originally checked against "file:", but on OS X, we just get "file"; this is probably true - // everywhere else too, but I will leave "file:" for the time being. -Zach - boolean isFileProtocol = "file".equals(url.getProtocol()) || "file:".equals(url.getProtocol()); - String host = url.getHost().trim(); - - return ((!isFileProtocol && ("".equals(host) || "/".equals(host))) - || (isFileProtocol && ("".equals(url.getPath().trim()) - || "localhost".equalsIgnoreCase(host)))); - } - - /** - * Form a ParsedURL, based on a relative path, using this as the base. - * - * @param relativeURLPath - * Path relative to this. - * @param errorDescriptor - * - * @return New ParsedURL based on this and the relative path. - */ - public final ParsedURL getRelative(String relativeURLPath, String errorDescriptor) - { - if (isFile()) - { - File newFile = Files.newFile(file, relativeURLPath); - // remove ..'s from path - if (newFile.getAbsolutePath().contains("..")) - { - try - { - File canonicalFile = newFile.getCanonicalFile(); - return new ParsedURL(canonicalFile); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - return new ParsedURL(newFile); - } - else - return getRelative(url, relativeURLPath, errorDescriptor); - } - - /** - * Form a ParsedURL, based on a relative path, using this as the base. - * - * @param relativeURLPath - * Path relative to this. - * - * @return New ParsedURL based on this and the relative path. - */ - public final ParsedURL getRelative(String relativeURLPath) - { - return getRelative(relativeURLPath, ""); - } - - /** - * Form a new ParsedURL, relative from a supplied base URL. Checks to see if the relativePath - * starts w a protocol spec. If so, calls getAbsolute(). Otherwise, forms a relative URL using the - * URL base. - * - * @param relativeURLPath - * @param errorDescriptor - * @return New ParsedURL - */ - public static ParsedURL getRelative(URL base, String relativeURLPath, String errorDescriptor) - { - if (relativeURLPath == null) - return null; - - ParsedURL result = null; - if (!relativeURLPath.startsWith("http://") && !relativeURLPath.startsWith("ftp://")) - { - try - { - URL resultURL = new URL(base, relativeURLPath); +package ecologylab.net; + +import java.io.File; +import java.io.IOException; +import java.net.CookieHandler; +import java.net.CookieManager; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.StringTokenizer; + +import ecologylab.collections.CollectionTools; +import ecologylab.generic.Debug; +import ecologylab.generic.IntSlot; +import ecologylab.generic.StringTools; +import ecologylab.io.Files; +import ecologylab.platformspecifics.FundamentalPlatformSpecifics; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; + +/** + * Extends the URL with many features for the convenience and power of network programmers. New + * class for manipulating and displaying URLs. + * + * Uses lazy evaluation to minimize storage allocation. + * + * @author andruid + * @author eunyee + * @author madhur + */ +public class ParsedURL extends Debug implements MimeType +{ + private static final String NOT_IN_THE_FORMAT_OF_A_WEB_ADDRESS = " is not in the format of a web address"; + + private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)"; + + /** + * this is the no hash url, that is, the one with # and anything after it stripped out. + */ + protected URL url = null; + + /** + * If this is built from an entity of the local file system, store a reference to the object for + * that here. + */ + File file; + + /** + * Directory that the document referred to by the URL resides in. + */ + protected URL directory = null; + + private ParsedURL directoryPURL; + + /** + * String representation of the URL. + */ + protected String string = null; + + /** + * Shorter version of the string, for printing in tight spaces. + */ + String shortString; + + /* lower case of the url string */ + protected String lc = null; + + /* suffix string of the url */ + protected String suffix = null; + + /* domain value string of the ulr */ + protected String domain = null; + + protected boolean includePrefix = true; + + private String fragment; + + public static CookieManager cookieManager = new CookieManager(); + + static + { + //cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); + CookieHandler.setDefault(cookieManager); + } + + public ParsedURL(URL url) + { + String hash = url.getRef(); + + if ("file".equals(url.getProtocol())) + { + String urlString = url.toString(); + if (urlString.startsWith("file://")) // this should be the case... + { + this.file = new File(urlString.substring(7)); + } + else // if not, try our hardest to make a good file + { + this.file = new File(url.getHost()+url.getPath()); + } + this.url = url; + } + else + { + this.url = url; + this.fragment = hash; + } + } + + /** + * + * @return true if this refers to a file, and that file exists. Also true if this does not refer to a file. + */ + public boolean isNotFileOrExists() + { + return (file == null) || file.exists(); + } + + /** + * Create a ParsedURL from a file. If the file is a directory, append "/" to the path, so that + * relative URLs will be formed properly later. + * + * @param file + */ + public ParsedURL(File file) + { + try + { + String urlString = "file://" + file.getAbsolutePath(); + urlString = urlString.replace('\\', '/'); + if (file.isDirectory()) + urlString += "/"; + this.url = new URL(urlString); + } + catch (MalformedURLException e) + { + e.printStackTrace(); + } + this.file = file; + } + + /* + * Constructor with a url string parameter. get absolute URL with getAbsolute() method. + */ + /* + * public ParsedURL(String urlString) { // The second parameter of getAbolute method is error + * description. this.url = getAbsolute(urlString, "").url(); } + */ + // ///////////////////////////////////////////////////////////////////// + /** + * Create a PURL from an absolute address. (Do it the quick and dirty way, providing less error + * handling.) NB: Only call this method if you are *sure* a MalformedURlException would never be + * produced. + * + */ + public static ParsedURL getAbsolute(String webAddr) + { + return getAbsolute(webAddr, "getAbsolute(String) "); + } + + public static ParsedURL get(URI uri) + { + return getAbsolute(uri.toString()); + } + + /** + * Create a PURL from an absolute address. + * + * @param webAddr + * url string + * @param errorDescriptor + * which will be printed out in the trace file if there is something happen converting + * from the url string to URL. + * @return ParsedURL from url string parameter named webAddr, or null if the param is malformed. + */ + public static ParsedURL getAbsolute(String webAddr, String errorDescriptor) + { + if (webAddr == null || webAddr.length() <= 7) + { + println("ERROR: ParsedURL.getAbsolute() webAddr is null or too short: [" + webAddr + "]"); + //Thread.dumpStack(); //We don't really need such a hostile message. + } + else + { + try + { + URL url = new URL(webAddr); + if (isUndetectedMalformedURL(url)) + return null; + return new ParsedURL(url); + } + catch (MalformedURLException e) + { + if (!"".equals(errorDescriptor)) + errorDescriptor = "\n" + errorDescriptor; + Debug.error(webAddr, NOT_IN_THE_FORMAT_OF_A_WEB_ADDRESS + "." + errorDescriptor); + } + } + return null; + } + + /** + * Determines a URL is malformed since Java fails to detect this. + * + * @param url + * @return + */ + private static boolean isUndetectedMalformedURL(URL url) + { + // originally checked against "file:", but on OS X, we just get "file"; this is probably true + // everywhere else too, but I will leave "file:" for the time being. -Zach + boolean isFileProtocol = "file".equals(url.getProtocol()) || "file:".equals(url.getProtocol()); + String host = url.getHost().trim(); + + return ((!isFileProtocol && ("".equals(host) || "/".equals(host))) + || (isFileProtocol && ("".equals(url.getPath().trim()) + || "localhost".equalsIgnoreCase(host)))); + } + + /** + * Form a ParsedURL, based on a relative path, using this as the base. + * + * @param relativeURLPath + * Path relative to this. + * @param errorDescriptor + * + * @return New ParsedURL based on this and the relative path. + */ + public final ParsedURL getRelative(String relativeURLPath, String errorDescriptor) + { + if (isFile()) + { + File newFile = Files.newFile(file, relativeURLPath); + // remove ..'s from path + if (newFile.getAbsolutePath().contains("..")) + { + try + { + File canonicalFile = newFile.getCanonicalFile(); + return new ParsedURL(canonicalFile); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + return new ParsedURL(newFile); + } + else + return getRelative(url, relativeURLPath, errorDescriptor); + } + + /** + * Form a ParsedURL, based on a relative path, using this as the base. + * + * @param relativeURLPath + * Path relative to this. + * + * @return New ParsedURL based on this and the relative path. + */ + public final ParsedURL getRelative(String relativeURLPath) + { + return getRelative(relativeURLPath, ""); + } + + /** + * Form a new ParsedURL, relative from a supplied base URL. Checks to see if the relativePath + * starts w a protocol spec. If so, calls getAbsolute(). Otherwise, forms a relative URL using the + * URL base. + * + * @param relativeURLPath + * @param errorDescriptor + * @return New ParsedURL + */ + public static ParsedURL getRelative(URL base, String relativeURLPath, String errorDescriptor) + { + if (relativeURLPath == null) + return null; + + ParsedURL result = null; + if (!relativeURLPath.startsWith("http://") && !relativeURLPath.startsWith("ftp://")) + { + try + { + URL resultURL = new URL(base, relativeURLPath); result = new ParsedURL(resultURL); - } - catch (MalformedURLException e) - { - if (!"".equals(errorDescriptor)) - errorDescriptor = "\n" + errorDescriptor; - Debug.error(relativeURLPath, NOT_IN_THE_FORMAT_OF_A_WEB_ADDRESS + "[" + base + "]." - + errorDescriptor); - } - } - else - return getAbsolute(relativeURLPath, errorDescriptor); - - return result; - } - - /** - * Use this as the source of stuff to translate from XML - * - * @param translationScope - * Translations that specify package + class names for translating. - * @return ElementState object derived from XML at the InputStream of this. - * @throws SIMPLTranslationException - */ - public Object translateFromXML(SimplTypesScope translationScope) - throws SIMPLTranslationException - { - return translationScope.deserialize(this, Format.XML); - } - - public static URL getURL(URL base, String path, String error) - { - // ??? might want to allow this default behaviour ??? - if (path == null) - return null; - try - { - // System.err.println("\nGENERIC - base, path, error = \n" + base + "\n" + path); - URL newURL = new URL(base, path); - // System.err.println("\nNEW URL = " + newURL); - return newURL; - } - catch (MalformedURLException e) - { - if (error != null) - throw new Error(e + "\n" + error + " " + base + " -> " + path); - return null; - } - } - - /** - * Uses lazy evaluation to minimize storage allocation. - * - * @return The URL as a String. - */ - @Override - public String toString() - { - String result = string; - if (result == null) - { - if (isFile() && includePrefix) - result = "file://" + file.toString().replace('\\', '/'); - else if (isFile() && !includePrefix) - result = file.toString().replace('\\', '/'); - else if (url == null) - result = "weirdly null"; - else - result = StringTools.pageString(url); - string = result; - } - return result; - } - - /** - * Uses lazy evaluation to minimize storage allocation. - * - * @return Lower case rendition of the URL String. - */ - public String lc() - { - String result = lc; - if (result == null) - { - result = toString().toLowerCase(); - lc = result; - } - return result; - } - - /** - * Uses lazy evaluation to minimize storage allocation. - * - * @return The suffix of the filename, in lower case. - */ - public String suffix() - { - String result = suffix; - if (result == null) - { - String path = url.getPath(); - if (path != null) - { - result = suffix(path.toLowerCase()); - } - // TODO make sure that there isnt code somewhere testing suffix for null! - if (result == null) - result = ""; - suffix = result; - } - return result; - } - - /** - * Form a ParsedURL based on this, if this is a directory. Otherwise, form the ParsedURL from the - * parent of this. Process files carefully to propagate their file-ness. - * - * @return - */ - public ParsedURL directoryPURL() - { - ParsedURL result = directoryPURL; - if (result == null) - { - if (isFile()) - { - if (file.isDirectory()) - result = this; - else - { - File parent = file.getParentFile(); - result = new ParsedURL(parent); - } - } - else - { - result = new ParsedURL(directory()); - } - this.directoryPURL = result; - } - return result; - } - - /** - * Get the URL for the directory associated with this. Requires looking for slash at the end, - * looking for a suffix or arguments. As a result, we sometimes add a slash at the end, sometimes - * peel off the filename. Result is cached a la lazy evaluation. - * - * @return Directory URL - */ - public URL directory() - { - URL result = this.directory; - if (result == null) - { - if (StringTools.endsWithSlash(toString())) - result = this.url; - if (result == null) - { - String suffix = suffix(); - try - { - String path = url.getPath(); - String args = url.getQuery(); - String protocol = url.getProtocol(); - String host = url.getHost(); - int port = url.getPort(); - if (suffix.length() == 0) - { // this is a directory that is unterminated by slash; we need to fix that - - if (path.length() == 0) - result = new URL(protocol, host, port, "/"); - else - { - if ((args == null) || (args.length() == 0)) - result = new URL(protocol, host, port, path + '/'); - else - // this is a tricky executable with no suffix - { - // result = null; - // drop down into the next block, and peel off that suffix-less executable name - } - } - } - // else - if (result == null) - { // you have a suffix, so we need to trim off the filename - int lastSlashIndex = path.lastIndexOf('/'); - if (lastSlashIndex == -1) - // suffix, but not within any subdirectory - result = new URL(protocol, host, port, "/"); - else - { - String pathThroughLastSlash = path.substring(0, lastSlashIndex + 1); - result = new URL(protocol, host, port, pathThroughLastSlash); - } - } - } - catch (MalformedURLException e) - { - debug("Unexpected ERROR forming directory."); - e.printStackTrace(); - } - } - this.directory = result; - } - return result; - } - - /** - * Uses lazy evaluation to minimize storage allocation. - * - * @return The domain of the URL. - */ - public String domain() - { - String result = domain; - if (result == null && (url != null)) - { - result = StringTools.domain(url); - domain = result; - } - return result; - } - - public boolean isNull() - { - return url == null && file == null; - } - - /** - * @return The suffix of the filename, in whatever case is found in the input string. - */ - public static String suffix(String lc) - { - int afterDot = lc.lastIndexOf('.') + 1; - int lastSlash = lc.lastIndexOf('/'); - String result = ((afterDot == 0) || (afterDot < lastSlash)) ? "" : lc.substring(afterDot); - return result; - } - - public String filename() - { - String lowerCase = noAnchorNoQueryPageString(); - int lastDot = lowerCase.lastIndexOf('.'); - int lastSlash = lowerCase.lastIndexOf('/'); - String result = (lastDot == 0 || (lastDot < lastSlash)) ? "" : lowerCase.substring(lastSlash, - lastDot); - return result; - } - - /** - * Uses lazy evaluation to minimize storage allocation. - * - * @return the URL. - */ - public final URL url() - { - return url; - } - - public final URL hashUrl() - { - - if (hashUrl == null) - return url(); - else - return hashUrl; - - } - - /* - * return noAnchor no query page string - */ - public String noAnchorNoQueryPageString() - { - return StringTools.noAnchorNoQueryPageString(url); - } - - /* - * return no anchor no page string. - */ - public String noAnchorPageString() - { - return StringTools.noAnchorPageString(url); - } - - /** - * @return true if the suffix of this is equal to that of the argument. - */ - public final boolean hasSuffix(String s) - { - return lc().endsWith(s); - // return suffix().equals(s); - } - - final static String unsupportedMimeStrings[] = - { "ai", "bmp", "eps", "ps", - "psd", "svg", "tif", "vrml", "doc", "xls", "pps", "ppt", "adp", "rtf", "vbs", "vsd", "wht", - "aif", "aiff", "aifc", "au", "mp3", "wav", "ra", "ram", "wm", "wma", "wmf", "wmp", "wms", - "wmv", "wmx", "wmz", "avi", "mov", "mpa", "mpeg", "mpg", "ppj", "swf", "spl", "qdb", "cab", - "chm", "gzip", "hqx", "jar", "lzh", "tar", "zip", "wpd", "xsl", }; - - final static HashMap unsupportedMimes = CollectionTools - .buildHashMapFromStrings(unsupportedMimeStrings); - - static final String[] unsupportedProtocolStrings = - { "mailto", "vbscript", "news", - "rtsp", "https", }; - - static final HashMap unsupportedProtocols = CollectionTools - .buildHashMapFromStrings(unsupportedProtocolStrings); - - static final String[] supportedProtocolStrings = - { "http", "ftp", "file", }; - - static final HashMap supportedProtocols = CollectionTools - .buildHashMapFromStrings(supportedProtocolStrings); - - static final String[] imgSuffixStrings; - - static final String[] SOME_IMG_SUFFIXES = { "jpg", "jpeg", "pjpg", "pjpeg", "gif", "png", }; - /* - * { "jpg", "jpeg", "pjpg", "pjpeg", "gif", "png", }; - */ - static final HashMap imgSuffixMap; // case - - static final String[] jpegMimeStrings = - { "jpg", "JPG", "jpeg", "JPEG", - "pjpg", "pjpeg", }; - - static final String[] gifMimeStrings = - { "gif", "GIF", }; - - static final String[] pngMimeStrings = - { "png", "PNG", }; - - static final HashMap jpegSuffixMap = CollectionTools - .buildHashMapFromStrings(jpegMimeStrings); - - static final String[] htmlSuffixStrings = - { "html", "htm", "stm", "php", - "jhtml", "jsp", "asp", "txt", "shtml", "pl", "plx", "exe" }; - - static final String[] noAlphaSuffixStrings = - { - "bmp", "BMP", "wbmp", "WBMP", - "jpg", "JPG", "jpeg", "JPEG", - "pjpg", "PJPG", "pjpeg", "PJPEG", - }; - - static final HashMap noAlphaSuffixMap = CollectionTools - .buildHashMapFromStrings(noAlphaSuffixStrings); - - static final HashMap htmlSuffixMap = CollectionTools - .buildHashMapFromStrings(htmlSuffixStrings); - - static final String[] pdfMimeStrings = - { "pdf" }; - - static final HashMap pdfSuffixMap = CollectionTools - .buildHashMapFromStrings(pdfMimeStrings); - - static final String[] rssMimeStrings = - { "rss", "xml" }; - - static final HashMap rssSuffixMap = CollectionTools - .buildHashMapFromStrings(rssMimeStrings); - - static final HashMap suffixesToMap = new HashMap(); - static - { - String[] platformSpecificImgFormats = null; - try - { - platformSpecificImgFormats = FundamentalPlatformSpecifics.get().getReaderFormatNames(); - } catch (Throwable e) - { - } - imgSuffixStrings = (platformSpecificImgFormats == null) ? SOME_IMG_SUFFIXES : platformSpecificImgFormats; - imgSuffixMap = CollectionTools.buildHashMapFromLCStrings(imgSuffixStrings); - - for (int i = 0; i < pdfMimeStrings.length; i++) - CollectionTools.stringIntMapEntry(suffixesToMap, pdfMimeStrings[i], PDF); - for (int i = 0; i < htmlSuffixStrings.length; i++) - CollectionTools.stringIntMapEntry(suffixesToMap, htmlSuffixStrings[i], HTML); - for (int i = 0; i < rssMimeStrings.length; i++) - CollectionTools.stringIntMapEntry(suffixesToMap, rssMimeStrings[i], RSS); - for (int i = 0; i < jpegMimeStrings.length; i++) - CollectionTools.stringIntMapEntry(suffixesToMap, jpegMimeStrings[i], JPG); - for (int i = 0; i < gifMimeStrings.length; i++) - CollectionTools.stringIntMapEntry(suffixesToMap, gifMimeStrings[i], GIF); - for (int i = 0; i < pngMimeStrings.length; i++) - CollectionTools.stringIntMapEntry(suffixesToMap, pngMimeStrings[i], PNG); - } - - /** - * Called while processing (parsing) HTML. Used to create new ParsedURLs from - * urlStrings in response to such as the a element's href attribute, the - * img element's src attribute, etc. - *

- * Does processing of some fancy stuff, like, in the case of javascript: URLs, it - * mines them for embedded absolute URLs, if possible, and uses only those embedded URLs. - * - * @param addressString - * This may be specify a relative or absolute url. - * - * @return The resulting ParsedURL. It may be null. It will never have protocol - * javascript:. - */ - public ParsedURL createFromHTML(String addressString) - { - return createFromHTML(addressString, false); - } - - /** - * Called while processing (parsing) HTML. Used to create new ParsedURLs from - * urlStrings in response to such as the a element's href attribute, the - * img element's src attribute, etc. - *

- * Does processing of some fancy stuff, like, in the case of javascript: URLs, it - * mines them for embedded absolute URLs, if possible, and uses only those embedded URLs. - * - * @param addressString - * This may be specify a relative or absolute url. - * - * @param fromSearchPage - * If false, then add / to the end of the URL if it seems to be a directory. - * - * @return The resulting ParsedURL. It may be null. It will never have protocol - * javascript:. - */ - public ParsedURL createFromHTML(String addressString, boolean fromSearchPage) - { - return createFromHTML(this, addressString, fromSearchPage); - } - - protected static ParsedURL get(URL url, String addressString) - { - try - { - return new ParsedURL(new URL(url, addressString)); - } - catch (MalformedURLException e) - { - println("ParsedURL.get() cant from url from: " + - /* url +"\n\taddressString = "+ */addressString); - // e.printStackTrace(); - } - return null; - } - - /** - * Called while processing (parsing) HTML. Used to create new ParsedURLs from - * urlStrings in response to such as the a element's href attribute, the - * img element's src attribute, etc. - *

- * Does processing of some fancy stuff, like, in the case of javascript: URLs, it - * mines them for embedded absolute URLs, if possible, and uses only those embedded URLs. - * - * @param addressString - * This may be specify a relative or absolute url. - * - * @param fromSearchPage - * If false, then add / to the end of the URL if it seems to be a directory. - * - * @return The resulting ParsedURL. It may be null. It will never have protocol - * javascript:. - */ - public static ParsedURL createFromHTML(ParsedURL contextPURL, String addressString, - boolean fromSearchPage) - { - if ((addressString == null) || (addressString.length() == 0)) - return null; - if (addressString.startsWith("#") || addressString.startsWith("mailto")) - { - // return get(contextPURL.url(), addressString); - return null; - } - - String lc = addressString.toLowerCase(); - boolean javascript = lc.startsWith("javascript:"); - - // mine urls from javascript quoted strings - if (javascript) - { - // !!! Could do an even better job here of mining quoted - // !!! javascript strings. - // println("Container.newURL("+s); - int http = lc.lastIndexOf("http://"); - // TODO learn to mine PDFs as well as html!! - int html = lc.lastIndexOf(".html"); - int pdf = lc.lastIndexOf(".pdf"); - // println("Container.newURL() checking javascript url:="+s+ - // " http="+http+" html="+html); - if (http > -1) - { // seek absolute web addrs - if ((html > -1) && (http < html)) - { - int end = html + 5; - addressString = addressString.substring(http, end); - // println("Container.newURL fixed javascript:= " + s); - lc = lc.substring(http, end); - javascript = false; - } - else if ((pdf > -1) && (http < pdf)) - { - int end = pdf + 4; - addressString = addressString.substring(http, end); - // println("Container.newURL fixed javascript:= " + s); - lc = lc.substring(http, end); - javascript = false; - } - } - else - { - // seek relative addresses - - // need to find the bounds of a quoted string, if there is one - } - // !!! What we should really do here is find quoted strings - // (usually with single quote, but perhaps double as well) - // (use regular expressions?? - are they fast enough?) - // and look at each one to see if either protocol is supported - // or suffix is htmlMime or imgMime. - } - if (javascript) - return null; - - char argDelim = '?'; - // url string always keep hash string. - String hashString = StringTools.EMPTY_STRING; - if (fromSearchPage) - { - // handle embedded http:// - int lastHttp = addressString.lastIndexOf("http://"); - // usually ? but could be & - if (lastHttp > 0) - { - // this is search engine crap - addressString = addressString.substring(lastHttp); - // debugA("now addressString="+addressString); - // handle any embedded args (for google mess) - argDelim = '&'; - } - } - else - { - // TODO do we really need to do any of this??????????????????????? - // 1) peel off hash - int hashPos = addressString.indexOf('#'); - // String hashString= StringTools.EMPTY_STRING; - - if (hashPos > -1) - { - hashString = addressString.substring(hashPos); - addressString = addressString.substring(0, hashPos); - } - // 2) peel off args - int argPos = addressString.indexOf(argDelim); - String argString = StringTools.EMPTY_STRING; - if (argPos > -1) - { - argString = addressString.substring(argPos); - addressString = addressString.substring(0, argPos); - } - // This seems uneccessary, crawling any wikimedia based site will break by adding an extra - // slash. - // else - // { - // // 3) if what's left is a directory (w/o a mime type),add slash - // int endingSlash = addressString.lastIndexOf('/'); - // int lastChar = addressString.length() - 1; - // if (endingSlash == -1) - // endingSlash++; - // if ((lastChar > 0) && - // (lastChar != endingSlash) && - // (addressString.substring(endingSlash).indexOf('.') == -1)) - // addressString += '/'; - // } - // 4) put back what we peeled off - addressString = addressString + argString + hashString; - } - int protocolEnd = addressString.indexOf(":"); - if (protocolEnd != -1) - { - // this is an absolute URL; check for supported protocol - String protocol = addressString.substring(0, protocolEnd); - if (protocolIsUnsupported(protocol)) - return null; - } - ParsedURL parsedUrl; - if (contextPURL == null || addressString.startsWith("http://")) - { - parsedUrl = getAbsolute(addressString, "in createFromHTML()"); - } - else - { - ParsedURL directoryPURL = contextPURL.directoryPURL(); - parsedUrl = directoryPURL.getRelative(addressString); - } - - return parsedUrl; - } - - /** - * - * @return A String version of the URL path, in which all punctuation characters have been changed - * into spaces. - */ - public String removePunctuation() - { - return StringTools.removePunctuation(toString()); - } - - /** - * @return true if they have same domains. false if they have different domains. - */ - public boolean sameDomain(ParsedURL other) - { - return (other != null) && domain().equals(other.domain()); - } - - /** - * @return true if they have same hosts. false if they have different hosts. - */ - public boolean sameHost(ParsedURL other) - { - return (other != null) && url.getHost().equals(other.url().getHost()); - } - - /** - * Use unsupportedMimes and protocolIsSupported to determine if this is content fit for - * processing. - * - * @return true if this seems to be a web addr we can crawl to. (currently that means html). - **/ - public boolean crawlable() - { - return protocolIsSupported() && !unsupportedMimes.containsKey(suffix()); - } - - /** - * Check whether the protocol is supported or not. Currently, only http and ftp are. - */ - public boolean protocolIsSupported() - { - return (url != null) && protocolIsSupported(url.getProtocol()); - } - - /** - * Check whether the protocol is supported or not. Currently, only http and ftp are. - */ - public static boolean protocolIsSupported(String protocol) - { - return supportedProtocols.containsKey(protocol); - } - - /** - * Check whether the protocol is supported or not. Currently, only http and ftp are. - */ - public boolean protocolIsUnsupported() - { - return (url != null) && protocolIsUnsupported(url.getProtocol()); - } - - /** - * Check whether the protocol is supported or not. Currently, only http and ftp are. - */ - public static boolean protocolIsUnsupported(String protocol) - { - return unsupportedProtocols.containsKey(protocol); - } - - /** - * @return true if this is an image file. - */ - public boolean isImg() - { - return isImageSuffix(suffix()); - } - - /** - * - * @param thatSuffix - * @return true if the suffix passed in is one for an image type that we can handle. - */ - public static boolean isImageSuffix(String thatSuffix) - { - return imgSuffixMap.containsKey(thatSuffix); - } - - /** - * @return true if this is a JPEG image file. - */ - public boolean isJpeg() - { - return jpegSuffixMap.containsKey(suffix()); - } - - /** - * @return true if we can tell the image file wont have alpha, just from its suffix. This is - * currently the case for jpeg and bmp. - */ - public boolean isNoAlpha() - { - return noAlphaSuffixMap.containsKey(suffix()); - } - - /** - * Test type of document this refers to. - * - * @return true if this refers to an HTML file - */ - public boolean isHTML() - { - return htmlSuffixMap.containsKey(suffix()); - } - - /** - * Test type of document this refers to. - * - * @return true if this refers to a PDF file - */ - public boolean isPDF() - { - return pdfSuffixMap.containsKey(suffix()); - } - - /** - * Test type of document this refers to. - * - * @return true if this refers to an RSS feed - */ - public boolean isRSS() - { - return rssSuffixMap.containsKey(suffix()); - } - - int mimeIndex = -1; - - /** - * Get MimeType index by seeing suffix(). - * - * @param parsedURL - */ - public int mimeIndex() - { - if (mimeIndex == -1) - { - String suffix = suffix(); - IntSlot mimeSlot = suffixesToMap.get(suffix); - mimeIndex = (mimeSlot != null) ? mimeSlot.value : UNKNOWN_MIME; - return mimeIndex; - } - else - return mimeIndex; - } - - public static int mimeIndex(String location) - { - int afterLastDot = location.lastIndexOf('.') + 1; - int result = UNKNOWN_MIME; - if ((afterLastDot > 0) && (location.length() > afterLastDot)) - { - String suffix = location.substring(afterLastDot); - IntSlot mimeSlot = suffixesToMap.get(suffix); - if (mimeSlot != null) - result = mimeSlot.value; - } - return result; - } - - /** - * Get Media MimeType indexes. Media MimeTypes are currently text and all kinds of images such as - * JPG, GIF, and PNG. - * - * @param parsedURL - */ - public int mediaMimeIndex() - { - return (mimeIndex() >= MimeType.UNKNOWN_MIME) ? MimeType.UNKNOWN_MIME : mimeIndex(); - } - - /* - * Check the suffix whether it is in the unsupportedMimes or not. If it is in the - * unsupportedMimes, return true, and if it is not, return false. - */ - public boolean isUnsupported() - { - return unsupportedMimes.containsKey(suffix()); - } - - /* - * return the inverse of isUnsupported(). Then, if the suffix is in the unsupportedMimes, return - * false, and if it is not, return true. - */ - public boolean supportedMime() - { - return !isUnsupported(); - } - - /** - * @return The directory of this, with protocol and host. - */ - public String directoryString() - { - String path = pathDirectoryString(); - - int portNum = url.getPort(); - String port = (portNum == -1) ? "" : ":" + portNum; - String host = url.getHost(); - String protocol = url.getProtocol(); - - int stringLength = protocol.length() + 3 + host.length() + port.length() + path.length(); - - StringBuffer buffy = new StringBuffer(stringLength); - buffy.append(protocol).append("://").append(host).append(port).append(path); - - return buffy.toString(); // dont copy; wont reuse buffy - } - - /** - * - * @return The directory of this, without protocol and host. - */ - public String pathDirectoryString() - { - String path = url.getPath(); - - int lastSlash = path.lastIndexOf("/"); - int lastDot = path.lastIndexOf("."); - if (lastDot > lastSlash) - path = path.substring(0, lastSlash); - - return path; - } - - public String path() - { - return (url == null) ? null : url.getFile(); - } - - /** - * Return true if the other object is either a ParsedURL or a URL that refers to the same location - * as this. Note: this is our own implementation. It is *much* faster and slightly less careful - * than JavaSoft's. Checks port, host, file, protocol, and query. Ignores ref = hash. - */ - @Override - public boolean equals(Object other) - { - if (other == null) - return false; - - boolean otherIsPURL = other instanceof ParsedURL; - boolean otherIsFile = other instanceof File; - if (otherIsPURL || otherIsFile) - { - File otherFile = otherIsFile ? (File) other : ((ParsedURL) other).file; - if (file != null) - { - return file.equals(otherFile); - } - if (otherFile != null) - return false; // other has file but this does not - } - else if (!(other instanceof URL)) - return false; // not a PURL or an URL - - URL url = this.url; - URL otherURL = otherIsPURL ? ((ParsedURL) other).url : (URL) other; - - if (url == null && otherURL == null) - return true; - - if (url == null || otherURL == null) - return false; - - // compare port - if (url.getPort() != otherURL.getPort()) - return false; - - // compare host - if (!url.getHost().equals(otherURL.getHost())) - return false; - - // compare file - if (!url.getFile().equals(otherURL.getFile())) - return false; - - // compare protocol - if (!url.getProtocol().equals(otherURL.getProtocol())) - return false; - - // compare arguments - return bothNullOrEqual(url.getQuery(), otherURL.getQuery()); - } - - private static boolean bothNullOrEqual(String a, String b) - { - return ((a == b) || // both are null or the same string - ((a != null) && a.equals(b))); // now safe to use a.equals() - } - - /** - * Hash this by its URL. - */ - @Override - public int hashCode() - { - if (url == null && file == null) - debug("help!"); - return (url != null) ? url.hashCode() : (file != null) ? file.hashCode() : -1; - } - - /** - * A shorter string for displaing in the modeline for debugging, and in popup messages. - */ - public String shortString() - { - String shortString = this.shortString; - if (shortString == null) - { - URL url = this.url; - if (url == null) - shortString = "null"; - else - { - String file = url.getFile(); - shortString = url.getHost() + "/.../" + file.substring(file.lastIndexOf('/') + 1); - } - this.shortString = shortString; - } - return shortString; - } - - /** - * True if this ParsedURL represents an entity on the local file system. - * - * @return true if this is a local File object. - */ - public boolean isFile() - { - return file != null; - } - - /** - * @return The file system object associated with this, if this is an entity on the local file - * system, or null, otherwise. - */ - public File file() - { - return file; - } - - /** - * Form a new ParsedURL from this, and the args passed in. A question mark is appended to the - * String form of this, and then args are appended. - * - * @param args - * @return ParsedURL with args after ? - */ - public ParsedURL withArgs(String args) - { - try - { - URL url = new URL(toString() + "?" + args); - return new ParsedURL(url); - } - catch (MalformedURLException e) - { - return null; - } - - } - - /** - * Returns the name of the file or directory denoted by this abstract pathname. This is just the - * last name in the pathname's name sequence. If the pathname's name sequence is empty, then the - * empty string is returned. - *

- * Analagous to File.getName(). - * - * @return Name of this, without directory, host, or protocol. - */ - public String getName() - { - URL url = this.url; - String path = url.getPath(); - int lastSlash = path.lastIndexOf('/'); - if (lastSlash > -1) - { - path = path.substring(lastSlash + 1); - } - return path; - } - - /** - * Basic ConnectionHelper. Does *nothing special* when encountering directories, re-directs, ... - */ - private static final ConnectionAdapter connectionAdapter = new ConnectionAdapter(); - - // Set the URLConnection timeout a little smaller than our DownloadMonitor timeout. - public static final int CONNECT_TIMEOUT = 15000; - - public static final int READ_TIMEOUT = 25000; - - /** - * Create a connection, using the standard timeouts of 23 seconds, and the super-basic - * ConnectionAdapter, which does *nothing special* when encountering directories, re-directs, ... - * - * @param connectionHelper - * @return - */ - public PURLConnection connect() - { - return connect(connectionAdapter); - } - - public PURLConnection connect(String userAgentName) - { - return connect(connectionAdapter, userAgentName); - } - - /** - * Create a connection, using the standard timeouts of 23 seconds. - * - * @param connectionHelper - * @return - */ - public PURLConnection connect(ConnectionHelper connectionHelper) - { - return connect(connectionHelper, DEFAULT_USER_AGENT, CONNECT_TIMEOUT, READ_TIMEOUT); - } - - public PURLConnection connect(ConnectionHelper connectionHelper, String userAgentString) - { - - return (userAgentString != null) ? connect(connectionHelper, userAgentString, CONNECT_TIMEOUT, - READ_TIMEOUT) : connect(connectionHelper); - } - - /** - * Create a connection. - * - * @param connectionHelper - * @param userAgent - * TODO - * @param connectionTimeout - * @param readTimeout - * @return - */ - public PURLConnection connect(ConnectionHelper connectionHelper, String userAgent, - int connectionTimeout, int readTimeout) - { - PURLConnection result = new PURLConnection(this); - result.connect(connectionHelper, userAgent, connectionTimeout, readTimeout); - return result; - } - - /** - * Free some memory resources. They can be re-allocated through subsequent lazy evaluation. The - * object is still fully functional after this call. - */ - public void resetCaches() - { - this.directory = null; - - this.string = null; - this.shortString = null; - this.lc = null; - this.suffix = null; - this.domain = null; - - if (directoryPURL != null) - { - this.directoryPURL.recycle(); - this.directoryPURL = null; - } - - // TODO -- is this too agressive?! - this.hashUrl = null; - } - - /** - * Free all all resources associated with this, rendering it no longer usable. - */ - public void recycle() - { - resetCaches(); - url = null; - file = null; - } - - public String host() - { - return (url == null) ? null : url.getHost(); - } - - /** - * - * @return A lightweight object corresponding to this, either a URL or a File - */ - public Object shadow() - { - return (url != null) ? url : file; - } - - public ParsedURL filterArgs(String...argsToKeep) - { - if (url != null) - { - String query = url.getQuery(); - StringTokenizer tokenizer = new StringTokenizer(query, "&"); - if (!tokenizer.hasMoreElements()) - return this; - StringBuilder resultQuery = new StringBuilder(noAnchorNoQueryPageString()); // initialize w base URL - boolean first = true; - while (tokenizer.hasMoreElements()) - { - String token = tokenizer.nextToken(); - for (String argToKeep: argsToKeep) - { - if (token.startsWith(argToKeep)) - { - if (first) - { - first = false; - resultQuery.append('?'); - } - else - resultQuery.append('&'); - resultQuery.append(token); - } - } - } - return getAbsolute(resultQuery.toString()); - } - return this; - } - public ParsedURL ignoreArgs(HashMap argsToIgnore) - { - if (url != null) - { - String query = url.getQuery(); - if (query !=null) - { - StringTokenizer tokenizer = new StringTokenizer(query, "&"); - if (!tokenizer.hasMoreElements()) - return this; - StringBuilder resultQuery = new StringBuilder(noAnchorNoQueryPageString()); // initialize w base URL - boolean first = true; - while (tokenizer.hasMoreElements()) - { - String token = tokenizer.nextToken(); - int argEnd = token.indexOf('='); - String arg = argEnd == -1 ? token : token.substring(0, argEnd); - if (!argsToIgnore.containsKey(arg)) - { - if (first) - { - first = false; - resultQuery.append('?'); - } - else - resultQuery.append('&'); - resultQuery.append(token); - } - } - return getAbsolute(resultQuery.toString()); - } - } - return this; - } - public String query() - { - return url.getQuery(); - } - static public void main(String[] args) - { - try - { - URL u = new URL("http://acm.org/citation.cfm?id=33344"); - System.out.println("query: " + u.getQuery() + "\n" + URLEncoder.encode("?")); - } - catch (MalformedURLException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - /** - * Extract arguments from the "query" portion of the URL (the part after ?). - * @param keepEmptyParams TODO - * - * @return HashMap of String name / value pairs. - */ - public HashMap extractParams(boolean keepEmptyParams) - { - return StringTools.doubleSplit(url, keepEmptyParams); - } - - /** - * Form a new ParsedURL using the base of this, while forming the query from a map of name / value pairs. - * - * @param newParamMap Map of name / value pairs. - * - * @return A new ParsedURL based on this one and the input argument map, or this, if that map is the same as in this. - */ - public ParsedURL updateParams(HashMap newParamMap) - { - HashMap oldParamMap = extractParams(true); - - String newArgString = StringTools.unDoubleSplit(newParamMap); - String noArgsNoQuery= StringTools.noAnchorPageString(url, false); - ParsedURL result = this; - if (newArgString != null && newArgString.length() > 0) - { - //TODO -- check to see if args are the same or different. - result = getAbsolute(noArgsNoQuery + '?' + newArgString); - } - else if (oldParamMap != null && oldParamMap.size() != 0) - { - result = getAbsolute(noArgsNoQuery); - } - return result; - } - - public ParsedURL changeHost(String newHost) - { - ParsedURL result = null; - if (newHost != null && newHost.length() > 0) - { - int port = url.getPort(); - try - { - URL newURL = (port > 0) ? new URL(url.getProtocol(), newHost, port, url.getFile()) : - new URL(url.getProtocol(), newHost, url.getFile()); - - result = new ParsedURL(newURL); - } - catch (MalformedURLException e) - { - e.printStackTrace(); - } - } - return result; - } - - public void setIncludePrefix(boolean includePrefix) - { - this.includePrefix = includePrefix; - } -} + } + catch (MalformedURLException e) + { + if (!"".equals(errorDescriptor)) + errorDescriptor = "\n" + errorDescriptor; + Debug.error(relativeURLPath, NOT_IN_THE_FORMAT_OF_A_WEB_ADDRESS + "[" + base + "]." + + errorDescriptor); + } + } + else + { + return getAbsolute(relativeURLPath, errorDescriptor); + } + + return result; + } + + /** + * Use this as the source of stuff to translate from XML + * + * @param translationScope + * Translations that specify package + class names for translating. + * @return ElementState object derived from XML at the InputStream of this. + * @throws SIMPLTranslationException + */ + public Object translateFromXML(SimplTypesScope translationScope) + throws SIMPLTranslationException + { + return translationScope.deserialize(this, Format.XML); + } + + public static URL getURL(URL base, String path, String error) + { + // ??? might want to allow this default behaviour ??? + if (path == null) + return null; + try + { + // System.err.println("\nGENERIC - base, path, error = \n" + base + "\n" + path); + URL newURL = new URL(base, path); + // System.err.println("\nNEW URL = " + newURL); + return newURL; + } + catch (MalformedURLException e) + { + if (error != null) + throw new Error(e + "\n" + error + " " + base + " -> " + path); + return null; + } + } + + /** + * Uses lazy evaluation to minimize storage allocation. + * + * @return The URL as a String. + */ + @Override + public String toString() + { + String result = string; + if (result == null) + { + if (isFile() && includePrefix) + result = "file://" + file.toString().replace('\\', '/'); + else if (isFile() && !includePrefix) + result = file.toString().replace('\\', '/'); + else if (url == null) + result = "weirdly null"; + else + result = StringTools.pageString(url); + string = result; + } + return result; + } + + /** + * Uses lazy evaluation to minimize storage allocation. + * + * @return Lower case rendition of the URL String. + */ + public String lc() + { + String result = lc; + if (result == null) + { + result = toString().toLowerCase(); + lc = result; + } + return result; + } + + /** + * Uses lazy evaluation to minimize storage allocation. + * + * @return The suffix of the filename, in lower case. + */ + public String suffix() + { + String result = suffix; + if (result == null) + { + String path = url.getPath(); + if (path != null) + { + result = suffix(path.toLowerCase()); + } + // TODO make sure that there isnt code somewhere testing suffix for null! + if (result == null) + result = ""; + suffix = result; + } + return result; + } + + /** + * Form a ParsedURL based on this, if this is a directory. Otherwise, form the ParsedURL from the + * parent of this. Process files carefully to propagate their file-ness. + * + * @return + */ + public ParsedURL directoryPURL() + { + ParsedURL result = directoryPURL; + if (result == null) + { + if (isFile()) + { + if (file.isDirectory()) + result = this; + else + { + File parent = file.getParentFile(); + result = new ParsedURL(parent); + } + } + else + { + result = new ParsedURL(directory()); + } + this.directoryPURL = result; + } + return result; + } + + /** + * Get the URL for the directory associated with this. Requires looking for slash at the end, + * looking for a suffix or arguments. As a result, we sometimes add a slash at the end, sometimes + * peel off the filename. Result is cached a la lazy evaluation. + * + * @return Directory URL + */ + public URL directory() + { + URL result = this.directory; + if (result == null) + { + if (StringTools.endsWithSlash(toString())) + result = this.url; + if (result == null) + { + String suffix = suffix(); + try + { + String path = url.getPath(); + String args = url.getQuery(); + String protocol = url.getProtocol(); + String host = url.getHost(); + int port = url.getPort(); + if (suffix.length() == 0) + { // this is a directory that is unterminated by slash; we need to fix that + + if (path.length() == 0) + result = new URL(protocol, host, port, "/"); + else + { + if ((args == null) || (args.length() == 0)) + result = new URL(protocol, host, port, path + '/'); + else + // this is a tricky executable with no suffix + { + // result = null; + // drop down into the next block, and peel off that suffix-less executable name + } + } + } + // else + if (result == null) + { // you have a suffix, so we need to trim off the filename + int lastSlashIndex = path.lastIndexOf('/'); + if (lastSlashIndex == -1) + // suffix, but not within any subdirectory + result = new URL(protocol, host, port, "/"); + else + { + String pathThroughLastSlash = path.substring(0, lastSlashIndex + 1); + result = new URL(protocol, host, port, pathThroughLastSlash); + } + } + } + catch (MalformedURLException e) + { + debug("Unexpected ERROR forming directory."); + e.printStackTrace(); + } + } + this.directory = result; + } + return result; + } + + /** + * Uses lazy evaluation to minimize storage allocation. + * + * @return The domain of the URL. + */ + public String domain() + { + String result = domain; + if (result == null && (url != null)) + { + result = StringTools.domain(url); + domain = result; + } + return result; + } + + public boolean isNull() + { + return url == null && file == null; + } + + /** + * @return The suffix of the filename, in whatever case is found in the input string. + */ + public static String suffix(String lc) + { + int afterDot = lc.lastIndexOf('.') + 1; + int lastSlash = lc.lastIndexOf('/'); + String result = ((afterDot == 0) || (afterDot < lastSlash)) ? "" : lc.substring(afterDot); + return result; + } + + public String filename() + { + String lowerCase = noAnchorNoQueryPageString(); + int lastDot = lowerCase.lastIndexOf('.'); + int lastSlash = lowerCase.lastIndexOf('/'); + String result = (lastDot == 0 || (lastDot < lastSlash)) ? "" : lowerCase.substring(lastSlash, + lastDot); + return result; + } + + /** + * Uses lazy evaluation to minimize storage allocation. + * + * @return the URL. + */ + public final URL url() + { + return url; + } + + public final URL hashUrl() + { + return url(); + } + + /* + * return noAnchor no query page string + */ + public String noAnchorNoQueryPageString() + { + return StringTools.noAnchorNoQueryPageString(url); + } + + /* + * return no anchor no page string. + */ + public String noAnchorPageString() + { + return StringTools.noAnchorPageString(url); + } + + /** + * @return true if the suffix of this is equal to that of the argument. + */ + public final boolean hasSuffix(String s) + { + return lc().endsWith(s); + // return suffix().equals(s); + } + + final static String unsupportedMimeStrings[] = + { "ai", "bmp", "eps", "ps", + "psd", "svg", "tif", "vrml", "doc", "xls", "pps", "ppt", "adp", "rtf", "vbs", "vsd", "wht", + "aif", "aiff", "aifc", "au", "mp3", "wav", "ra", "ram", "wm", "wma", "wmf", "wmp", "wms", + "wmv", "wmx", "wmz", "avi", "mov", "mpa", "mpeg", "mpg", "ppj", "swf", "spl", "qdb", "cab", + "chm", "gzip", "hqx", "jar", "lzh", "tar", "zip", "wpd", "xsl", }; + + final static HashMap unsupportedMimes = CollectionTools + .buildHashMapFromStrings(unsupportedMimeStrings); + + static final String[] unsupportedProtocolStrings = + { "mailto", "vbscript", "news", + "rtsp", "https", }; + + static final HashMap unsupportedProtocols = CollectionTools + .buildHashMapFromStrings(unsupportedProtocolStrings); + + static final String[] supportedProtocolStrings = + { "http", "ftp", "file", }; + + static final HashMap supportedProtocols = CollectionTools + .buildHashMapFromStrings(supportedProtocolStrings); + + static final String[] imgSuffixStrings; + + static final String[] SOME_IMG_SUFFIXES = { "jpg", "jpeg", "pjpg", "pjpeg", "gif", "png", }; + /* + * { "jpg", "jpeg", "pjpg", "pjpeg", "gif", "png", }; + */ + static final HashMap imgSuffixMap; // case + + static final String[] jpegMimeStrings = + { "jpg", "JPG", "jpeg", "JPEG", + "pjpg", "pjpeg", }; + + static final String[] gifMimeStrings = + { "gif", "GIF", }; + + static final String[] pngMimeStrings = + { "png", "PNG", }; + + static final HashMap jpegSuffixMap = CollectionTools + .buildHashMapFromStrings(jpegMimeStrings); + + static final String[] htmlSuffixStrings = + { "html", "htm", "stm", "php", + "jhtml", "jsp", "asp", "txt", "shtml", "pl", "plx", "exe" }; + + static final String[] noAlphaSuffixStrings = + { + "bmp", "BMP", "wbmp", "WBMP", + "jpg", "JPG", "jpeg", "JPEG", + "pjpg", "PJPG", "pjpeg", "PJPEG", + }; + + static final HashMap noAlphaSuffixMap = CollectionTools + .buildHashMapFromStrings(noAlphaSuffixStrings); + + static final HashMap htmlSuffixMap = CollectionTools + .buildHashMapFromStrings(htmlSuffixStrings); + + static final String[] pdfMimeStrings = + { "pdf" }; + + static final HashMap pdfSuffixMap = CollectionTools + .buildHashMapFromStrings(pdfMimeStrings); + + static final String[] rssMimeStrings = + { "rss", "xml" }; + + static final HashMap rssSuffixMap = CollectionTools + .buildHashMapFromStrings(rssMimeStrings); + + static final HashMap suffixesToMap = new HashMap(); + static + { + String[] platformSpecificImgFormats = null; + try + { + platformSpecificImgFormats = FundamentalPlatformSpecifics.get().getReaderFormatNames(); + } catch (Throwable e) + { + } + imgSuffixStrings = (platformSpecificImgFormats == null) ? SOME_IMG_SUFFIXES : platformSpecificImgFormats; + imgSuffixMap = CollectionTools.buildHashMapFromLCStrings(imgSuffixStrings); + + for (int i = 0; i < pdfMimeStrings.length; i++) + CollectionTools.stringIntMapEntry(suffixesToMap, pdfMimeStrings[i], PDF); + for (int i = 0; i < htmlSuffixStrings.length; i++) + CollectionTools.stringIntMapEntry(suffixesToMap, htmlSuffixStrings[i], HTML); + for (int i = 0; i < rssMimeStrings.length; i++) + CollectionTools.stringIntMapEntry(suffixesToMap, rssMimeStrings[i], RSS); + for (int i = 0; i < jpegMimeStrings.length; i++) + CollectionTools.stringIntMapEntry(suffixesToMap, jpegMimeStrings[i], JPG); + for (int i = 0; i < gifMimeStrings.length; i++) + CollectionTools.stringIntMapEntry(suffixesToMap, gifMimeStrings[i], GIF); + for (int i = 0; i < pngMimeStrings.length; i++) + CollectionTools.stringIntMapEntry(suffixesToMap, pngMimeStrings[i], PNG); + } + + /** + * Called while processing (parsing) HTML. Used to create new ParsedURLs from + * urlStrings in response to such as the a element's href attribute, the + * img element's src attribute, etc. + *

+ * Does processing of some fancy stuff, like, in the case of javascript: URLs, it + * mines them for embedded absolute URLs, if possible, and uses only those embedded URLs. + * + * @param addressString + * This may be specify a relative or absolute url. + * + * @return The resulting ParsedURL. It may be null. It will never have protocol + * javascript:. + */ + public ParsedURL createFromHTML(String addressString) + { + return createFromHTML(addressString, false); + } + + /** + * Called while processing (parsing) HTML. Used to create new ParsedURLs from + * urlStrings in response to such as the a element's href attribute, the + * img element's src attribute, etc. + *

+ * Does processing of some fancy stuff, like, in the case of javascript: URLs, it + * mines them for embedded absolute URLs, if possible, and uses only those embedded URLs. + * + * @param addressString + * This may be specify a relative or absolute url. + * + * @param fromSearchPage + * If false, then add / to the end of the URL if it seems to be a directory. + * + * @return The resulting ParsedURL. It may be null. It will never have protocol + * javascript:. + */ + public ParsedURL createFromHTML(String addressString, boolean fromSearchPage) + { + return createFromHTML(this, addressString, fromSearchPage); + } + + protected static ParsedURL get(URL url, String addressString) + { + try + { + return new ParsedURL(new URL(url, addressString)); + } + catch (MalformedURLException e) + { + println("ParsedURL.get() cant from url from: " + + /* url +"\n\taddressString = "+ */addressString); + // e.printStackTrace(); + } + return null; + } + + /** + * Called while processing (parsing) HTML. Used to create new ParsedURLs from + * urlStrings in response to such as the a element's href attribute, the + * img element's src attribute, etc. + *

+ * Does processing of some fancy stuff, like, in the case of javascript: URLs, it + * mines them for embedded absolute URLs, if possible, and uses only those embedded URLs. + * + * @param addressString + * This may be specify a relative or absolute url. + * + * @param fromSearchPage + * If false, then add / to the end of the URL if it seems to be a directory. + * + * @return The resulting ParsedURL. It may be null. It will never have protocol + * javascript:. + */ + public static ParsedURL createFromHTML(ParsedURL contextPURL, String addressString, + boolean fromSearchPage) + { + if ((addressString == null) || (addressString.length() == 0)) + return null; + if (addressString.startsWith("#") || addressString.startsWith("mailto")) + { + // return get(contextPURL.url(), addressString); + return null; + } + + String lc = addressString.toLowerCase(); + boolean javascript = lc.startsWith("javascript:"); + + // mine urls from javascript quoted strings + if (javascript) + { + // !!! Could do an even better job here of mining quoted + // !!! javascript strings. + // println("Container.newURL("+s); + int http = lc.lastIndexOf("http://"); + // TODO learn to mine PDFs as well as html!! + int html = lc.lastIndexOf(".html"); + int pdf = lc.lastIndexOf(".pdf"); + // println("Container.newURL() checking javascript url:="+s+ + // " http="+http+" html="+html); + if (http > -1) + { // seek absolute web addrs + if ((html > -1) && (http < html)) + { + int end = html + 5; + addressString = addressString.substring(http, end); + // println("Container.newURL fixed javascript:= " + s); + lc = lc.substring(http, end); + javascript = false; + } + else if ((pdf > -1) && (http < pdf)) + { + int end = pdf + 4; + addressString = addressString.substring(http, end); + // println("Container.newURL fixed javascript:= " + s); + lc = lc.substring(http, end); + javascript = false; + } + } + else + { + // seek relative addresses + + // need to find the bounds of a quoted string, if there is one + } + // !!! What we should really do here is find quoted strings + // (usually with single quote, but perhaps double as well) + // (use regular expressions?? - are they fast enough?) + // and look at each one to see if either protocol is supported + // or suffix is htmlMime or imgMime. + } + if (javascript) + return null; + + char argDelim = '?'; + // url string always keep hash string. + String hashString = StringTools.EMPTY_STRING; + if (fromSearchPage) + { + // handle embedded http:// + int lastHttp = addressString.lastIndexOf("http://"); + // usually ? but could be & + if (lastHttp > 0) + { + // this is search engine crap + addressString = addressString.substring(lastHttp); + // debugA("now addressString="+addressString); + // handle any embedded args (for google mess) + argDelim = '&'; + } + } + else + { + // TODO do we really need to do any of this??????????????????????? + // 1) peel off hash + int hashPos = addressString.indexOf('#'); + // String hashString= StringTools.EMPTY_STRING; + + if (hashPos > -1) + { + hashString = addressString.substring(hashPos); + addressString = addressString.substring(0, hashPos); + } + // 2) peel off args + int argPos = addressString.indexOf(argDelim); + String argString = StringTools.EMPTY_STRING; + if (argPos > -1) + { + argString = addressString.substring(argPos); + addressString = addressString.substring(0, argPos); + } + // This seems uneccessary, crawling any wikimedia based site will break by adding an extra + // slash. + // else + // { + // // 3) if what's left is a directory (w/o a mime type),add slash + // int endingSlash = addressString.lastIndexOf('/'); + // int lastChar = addressString.length() - 1; + // if (endingSlash == -1) + // endingSlash++; + // if ((lastChar > 0) && + // (lastChar != endingSlash) && + // (addressString.substring(endingSlash).indexOf('.') == -1)) + // addressString += '/'; + // } + // 4) put back what we peeled off + addressString = addressString + argString + hashString; + } + int protocolEnd = addressString.indexOf(":"); + if (protocolEnd != -1) + { + // this is an absolute URL; check for supported protocol + String protocol = addressString.substring(0, protocolEnd); + if (protocolIsUnsupported(protocol)) + return null; + } + ParsedURL parsedUrl; + if (contextPURL == null || addressString.startsWith("http://")) + { + parsedUrl = getAbsolute(addressString, "in createFromHTML()"); + } + else + { + ParsedURL directoryPURL = contextPURL.directoryPURL(); + parsedUrl = directoryPURL.getRelative(addressString); + } + + return parsedUrl; + } + + /** + * + * @return A String version of the URL path, in which all punctuation characters have been changed + * into spaces. + */ + public String removePunctuation() + { + return StringTools.removePunctuation(toString()); + } + + /** + * @return true if they have same domains. false if they have different domains. + */ + public boolean sameDomain(ParsedURL other) + { + return (other != null) && domain().equals(other.domain()); + } + + /** + * @return true if they have same hosts. false if they have different hosts. + */ + public boolean sameHost(ParsedURL other) + { + return (other != null) && url.getHost().equals(other.url().getHost()); + } + + /** + * Use unsupportedMimes and protocolIsSupported to determine if this is content fit for + * processing. + * + * @return true if this seems to be a web addr we can crawl to. (currently that means html). + **/ + public boolean crawlable() + { + return protocolIsSupported() && !unsupportedMimes.containsKey(suffix()); + } + + /** + * Check whether the protocol is supported or not. Currently, only http and ftp are. + */ + public boolean protocolIsSupported() + { + return (url != null) && protocolIsSupported(url.getProtocol()); + } + + /** + * Check whether the protocol is supported or not. Currently, only http and ftp are. + */ + public static boolean protocolIsSupported(String protocol) + { + return supportedProtocols.containsKey(protocol); + } + + /** + * Check whether the protocol is supported or not. Currently, only http and ftp are. + */ + public boolean protocolIsUnsupported() + { + return (url != null) && protocolIsUnsupported(url.getProtocol()); + } + + /** + * Check whether the protocol is supported or not. Currently, only http and ftp are. + */ + public static boolean protocolIsUnsupported(String protocol) + { + return unsupportedProtocols.containsKey(protocol); + } + + /** + * @return true if this is an image file. + */ + public boolean isImg() + { + return isImageSuffix(suffix()); + } + + /** + * + * @param thatSuffix + * @return true if the suffix passed in is one for an image type that we can handle. + */ + public static boolean isImageSuffix(String thatSuffix) + { + return imgSuffixMap.containsKey(thatSuffix); + } + + /** + * @return true if this is a JPEG image file. + */ + public boolean isJpeg() + { + return jpegSuffixMap.containsKey(suffix()); + } + + /** + * @return true if we can tell the image file wont have alpha, just from its suffix. This is + * currently the case for jpeg and bmp. + */ + public boolean isNoAlpha() + { + return noAlphaSuffixMap.containsKey(suffix()); + } + + /** + * Test type of document this refers to. + * + * @return true if this refers to an HTML file + */ + public boolean isHTML() + { + return htmlSuffixMap.containsKey(suffix()); + } + + /** + * Test type of document this refers to. + * + * @return true if this refers to a PDF file + */ + public boolean isPDF() + { + return pdfSuffixMap.containsKey(suffix()); + } + + /** + * Test type of document this refers to. + * + * @return true if this refers to an RSS feed + */ + public boolean isRSS() + { + return rssSuffixMap.containsKey(suffix()); + } + + int mimeIndex = -1; + + /** + * Get MimeType index by seeing suffix(). + * + * @param parsedURL + */ + public int mimeIndex() + { + if (mimeIndex == -1) + { + String suffix = suffix(); + IntSlot mimeSlot = suffixesToMap.get(suffix); + mimeIndex = (mimeSlot != null) ? mimeSlot.value : UNKNOWN_MIME; + return mimeIndex; + } + else + return mimeIndex; + } + + public static int mimeIndex(String location) + { + int afterLastDot = location.lastIndexOf('.') + 1; + int result = UNKNOWN_MIME; + if ((afterLastDot > 0) && (location.length() > afterLastDot)) + { + String suffix = location.substring(afterLastDot); + IntSlot mimeSlot = suffixesToMap.get(suffix); + if (mimeSlot != null) + result = mimeSlot.value; + } + return result; + } + + /** + * Get Media MimeType indexes. Media MimeTypes are currently text and all kinds of images such as + * JPG, GIF, and PNG. + * + * @param parsedURL + */ + public int mediaMimeIndex() + { + return (mimeIndex() >= MimeType.UNKNOWN_MIME) ? MimeType.UNKNOWN_MIME : mimeIndex(); + } + + /* + * Check the suffix whether it is in the unsupportedMimes or not. If it is in the + * unsupportedMimes, return true, and if it is not, return false. + */ + public boolean isUnsupported() + { + return unsupportedMimes.containsKey(suffix()); + } + + /* + * return the inverse of isUnsupported(). Then, if the suffix is in the unsupportedMimes, return + * false, and if it is not, return true. + */ + public boolean supportedMime() + { + return !isUnsupported(); + } + + /** + * @return The directory of this, with protocol and host. + */ + public String directoryString() + { + String path = pathDirectoryString(); + + int portNum = url.getPort(); + String port = (portNum == -1) ? "" : ":" + portNum; + String host = url.getHost(); + String protocol = url.getProtocol(); + + int stringLength = protocol.length() + 3 + host.length() + port.length() + path.length(); + + StringBuffer buffy = new StringBuffer(stringLength); + buffy.append(protocol).append("://").append(host).append(port).append(path); + + return buffy.toString(); // dont copy; wont reuse buffy + } + + /** + * + * @return The directory of this, without protocol and host. + */ + public String pathDirectoryString() + { + String path = url.getPath(); + + int lastSlash = path.lastIndexOf("/"); + int lastDot = path.lastIndexOf("."); + if (lastDot > lastSlash) + path = path.substring(0, lastSlash); + + return path; + } + + public String path() + { + return (url == null) ? null : url.getFile(); + } + + public String pathNoQuery() + { + return url.getPath(); + } + + /** + * Return true if the other object is either a ParsedURL or a URL that refers to the same location + * as this. Note: this is our own implementation. It is *much* faster and slightly less careful + * than JavaSoft's. Checks port, host, file, protocol, and query. Ignores ref = hash. + */ + @Override + public boolean equals(Object other) + { + if (other == null) + return false; + + boolean otherIsPURL = other instanceof ParsedURL; + boolean otherIsFile = other instanceof File; + if (otherIsPURL || otherIsFile) + { + File otherFile = otherIsFile ? (File) other : ((ParsedURL) other).file; + if (file != null) + { + return file.equals(otherFile); + } + if (otherFile != null) + return false; // other has file but this does not + } + else if (!(other instanceof URL)) + return false; // not a PURL or an URL + + URL url = this.url; + URL otherURL = otherIsPURL ? ((ParsedURL) other).url : (URL) other; + + if (url == null && otherURL == null) + return true; + + if (url == null || otherURL == null) + return false; + + // compare port + if (url.getPort() != otherURL.getPort()) + return false; + + // compare host + if (!url.getHost().equals(otherURL.getHost())) + return false; + + // compare file + if (!url.getFile().equals(otherURL.getFile())) + return false; + + // compare protocol + if (!url.getProtocol().equals(otherURL.getProtocol())) + return false; + + // compare arguments + return bothNullOrEqual(url.getQuery(), otherURL.getQuery()); + } + + private static boolean bothNullOrEqual(String a, String b) + { + return ((a == b) || // both are null or the same string + ((a != null) && a.equals(b))); // now safe to use a.equals() + } + + /** + * Hash this by its URL. + */ + @Override + public int hashCode() + { + if (url == null && file == null) + debug("help!"); + return (url != null) ? url.hashCode() : (file != null) ? file.hashCode() : -1; + } + + /** + * A shorter string for displaing in the modeline for debugging, and in popup messages. + */ + public String shortString() + { + String shortString = this.shortString; + if (shortString == null) + { + URL url = this.url; + if (url == null) + shortString = "null"; + else + { + String file = url.getFile(); + shortString = url.getHost() + "/.../" + file.substring(file.lastIndexOf('/') + 1); + } + this.shortString = shortString; + } + return shortString; + } + + /** + * True if this ParsedURL represents an entity on the local file system. + * + * @return true if this is a local File object. + */ + public boolean isFile() + { + return file != null; + } + + /** + * @return The file system object associated with this, if this is an entity on the local file + * system, or null, otherwise. + */ + public File file() + { + return file; + } + + /** + * Form a new ParsedURL from this, and the args passed in. A question mark is appended to the + * String form of this, and then args are appended. + * + * @param args + * @return ParsedURL with args after ? + */ + public ParsedURL withArgs(String args) + { + try + { + URL url = new URL(toString() + "?" + args); + return new ParsedURL(url); + } + catch (MalformedURLException e) + { + return null; + } + + } + + /** + * Returns the name of the file or directory denoted by this abstract pathname. This is just the + * last name in the pathname's name sequence. If the pathname's name sequence is empty, then the + * empty string is returned. + *

+ * Analagous to File.getName(). + * + * @return Name of this, without directory, host, or protocol. + */ + public String getName() + { + URL url = this.url; + String path = url.getPath(); + int lastSlash = path.lastIndexOf('/'); + if (lastSlash > -1) + { + path = path.substring(lastSlash + 1); + } + return path; + } + + /** + * Basic ConnectionHelper. Does *nothing special* when encountering directories, re-directs, ... + */ + private static final ConnectionAdapter connectionAdapter = new ConnectionAdapter(); + + // Set the URLConnection timeout a little smaller than our DownloadMonitor timeout. + public static final int CONNECT_TIMEOUT = 15000; + + public static final int READ_TIMEOUT = 25000; + + /** + * Create a connection, using the standard timeouts of 23 seconds, and the super-basic + * ConnectionAdapter, which does *nothing special* when encountering directories, re-directs, ... + * + * @param connectionHelper + * @return + */ + public PURLConnection connect() + { + return connect(connectionAdapter); + } + + public PURLConnection connect(String userAgentName) + { + return connect(connectionAdapter, userAgentName); + } + + /** + * Create a connection, using the standard timeouts of 23 seconds. + * + * @param connectionHelper + * @return + */ + public PURLConnection connect(ConnectionHelper connectionHelper) + { + return connect(connectionHelper, DEFAULT_USER_AGENT, CONNECT_TIMEOUT, READ_TIMEOUT); + } + + public PURLConnection connect(ConnectionHelper connectionHelper, String userAgentString) + { + + return (userAgentString != null) ? connect(connectionHelper, userAgentString, CONNECT_TIMEOUT, + READ_TIMEOUT) : connect(connectionHelper); + } + + /** + * Create a connection. + * + * @param connectionHelper + * @param userAgent + * TODO + * @param connectionTimeout + * @param readTimeout + * @return + */ + public PURLConnection connect(ConnectionHelper connectionHelper, String userAgent, + int connectionTimeout, int readTimeout) + { + PURLConnection result = new PURLConnection(this); + result.connect(connectionHelper, userAgent, connectionTimeout, readTimeout); + return result; + } + + /** + * Free some memory resources. They can be re-allocated through subsequent lazy evaluation. The + * object is still fully functional after this call. + */ + public void resetCaches() + { + this.directory = null; + + this.string = null; + this.shortString = null; + this.lc = null; + this.suffix = null; + this.domain = null; + + if (directoryPURL != null) + { + this.directoryPURL.recycle(); + this.directoryPURL = null; + } + } + + /** + * Free all all resources associated with this, rendering it no longer usable. + */ + public void recycle() + { + resetCaches(); + url = null; + file = null; + } + + public String host() + { + return (url == null) ? null : url.getHost(); + } + + /** + * + * @return A lightweight object corresponding to this, either a URL or a File + */ + public Object shadow() + { + return (url != null) ? url : file; + } + + public ParsedURL filterArgs(String...argsToKeep) + { + if (url != null) + { + String query = url.getQuery(); + StringTokenizer tokenizer = new StringTokenizer(query, "&"); + if (!tokenizer.hasMoreElements()) + return this; + StringBuilder resultQuery = new StringBuilder(noAnchorNoQueryPageString()); // initialize w base URL + boolean first = true; + while (tokenizer.hasMoreElements()) + { + String token = tokenizer.nextToken(); + for (String argToKeep: argsToKeep) + { + if (token.startsWith(argToKeep)) + { + if (first) + { + first = false; + resultQuery.append('?'); + } + else + resultQuery.append('&'); + resultQuery.append(token); + } + } + } + return getAbsolute(resultQuery.toString()); + } + return this; + } + public ParsedURL ignoreArgs(HashMap argsToIgnore) + { + if (url != null) + { + String query = url.getQuery(); + if (query !=null) + { + StringTokenizer tokenizer = new StringTokenizer(query, "&"); + if (!tokenizer.hasMoreElements()) + return this; + StringBuilder resultQuery = new StringBuilder(noAnchorNoQueryPageString()); // initialize w base URL + boolean first = true; + while (tokenizer.hasMoreElements()) + { + String token = tokenizer.nextToken(); + int argEnd = token.indexOf('='); + String arg = argEnd == -1 ? token : token.substring(0, argEnd); + if (!argsToIgnore.containsKey(arg)) + { + if (first) + { + first = false; + resultQuery.append('?'); + } + else + resultQuery.append('&'); + resultQuery.append(token); + } + } + return getAbsolute(resultQuery.toString()); + } + } + return this; + } + public String query() + { + return url.getQuery(); + } + static public void main(String[] args) + { + try + { + URL u = new URL("http://acm.org/citation.cfm?id=33344"); + System.out.println("query: " + u.getQuery() + "\n" + URLEncoder.encode("?")); + } + catch (MalformedURLException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Extract arguments from the "query" portion of the URL (the part after ?). + * @param keepEmptyParams TODO + * + * @return HashMap of String name / value pairs. + */ + public HashMap extractParams(boolean keepEmptyParams) + { + return StringTools.doubleSplit(url, keepEmptyParams); + } + + /** + * Form a new ParsedURL using the base of this, while forming the query from a map of name / value pairs. + * + * @param newParamMap Map of name / value pairs. + * + * @return A new ParsedURL based on this one and the input argument map, or this, if that map is the same as in this. + */ + public ParsedURL updateParams(HashMap newParamMap) + { + HashMap oldParamMap = extractParams(true); + + String newArgString = StringTools.unDoubleSplit(newParamMap); + String noArgsNoQuery= StringTools.noAnchorPageString(url, false); + ParsedURL result = this; + if (newArgString != null && newArgString.length() > 0) + { + //TODO -- check to see if args are the same or different. + result = getAbsolute(noArgsNoQuery + '?' + newArgString); + } + else if (oldParamMap != null && oldParamMap.size() != 0) + { + result = getAbsolute(noArgsNoQuery); + } + return result; + } + + public ParsedURL changeHost(String newHost) + { + ParsedURL result = null; + if (newHost != null && newHost.length() > 0) + { + int port = url.getPort(); + try + { + URL newURL = (port > 0) ? new URL(url.getProtocol(), newHost, port, url.getFile()) : + new URL(url.getProtocol(), newHost, url.getFile()); + + result = new ParsedURL(newURL); + } + catch (MalformedURLException e) + { + e.printStackTrace(); + } + } + return result; + } + + public void setIncludePrefix(boolean includePrefix) + { + this.includePrefix = includePrefix; + } + + public String fragment() + { + return fragment == null ? url.getRef() : fragment; + } + +} diff --git a/simplCore/src/ecologylab/net/package.html b/simplCore/src/ecologylab/net/package.html index 5f26f758..d9fd1e21 100644 --- a/simplCore/src/ecologylab/net/package.html +++ b/simplCore/src/ecologylab/net/package.html @@ -1,4 +1,4 @@ - -Infrastructural classes that provide a more powerful API for network -programming. - + +Infrastructural classes that provide a more powerful API for network +programming. + diff --git a/simplCore/src/ecologylab/oodss/distributed/client/ClientStatusListener.java b/simplCore/src/ecologylab/oodss/distributed/client/ClientStatusListener.java index 0cd0f14d..542bc16e 100644 --- a/simplCore/src/ecologylab/oodss/distributed/client/ClientStatusListener.java +++ b/simplCore/src/ecologylab/oodss/distributed/client/ClientStatusListener.java @@ -1,12 +1,12 @@ -package ecologylab.oodss.distributed.client; - -public interface ClientStatusListener -{ - /** - * Invoked when the client's connection status changes. - * - * @param connect - * true if the client connected; false if the client disconnected. - */ - public void clientConnectionStatusChanged(boolean connect); -} +package ecologylab.oodss.distributed.client; + +public interface ClientStatusListener +{ + /** + * Invoked when the client's connection status changes. + * + * @param connect + * true if the client connected; false if the client disconnected. + */ + public void clientConnectionStatusChanged(boolean connect); +} diff --git a/simplCore/src/ecologylab/oodss/distributed/client/package.html b/simplCore/src/ecologylab/oodss/distributed/client/package.html index 04218f79..a5485a41 100644 --- a/simplCore/src/ecologylab/oodss/distributed/client/package.html +++ b/simplCore/src/ecologylab/oodss/distributed/client/package.html @@ -1,3 +1,3 @@ - -Clients for distributed computing services. - + +Clients for distributed computing services. + diff --git a/simplCore/src/ecologylab/oodss/distributed/common/BaseStates.java b/simplCore/src/ecologylab/oodss/distributed/common/BaseStates.java index a3383369..32cd5741 100644 --- a/simplCore/src/ecologylab/oodss/distributed/common/BaseStates.java +++ b/simplCore/src/ecologylab/oodss/distributed/common/BaseStates.java @@ -1,22 +1,22 @@ -/* - * Created on May 15, 2006 - */ -package ecologylab.oodss.distributed.common; - -/** - * States for clients in a networked application. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public interface BaseStates -{ - /** Client not currently connected to any server. */ - public static final String NOT_CONNECTED = "Not connected."; - - /** Client currently attempting to connect to a server. */ - public static final String CONNECTING = "Connecting."; - - /** Client connected to a server. */ - public static final String CONNECTED = "Connected."; -} +/* + * Created on May 15, 2006 + */ +package ecologylab.oodss.distributed.common; + +/** + * States for clients in a networked application. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public interface BaseStates +{ + /** Client not currently connected to any server. */ + public static final String NOT_CONNECTED = "Not connected."; + + /** Client currently attempting to connect to a server. */ + public static final String CONNECTING = "Connecting."; + + /** Client connected to a server. */ + public static final String CONNECTED = "Connected."; +} diff --git a/simplCore/src/ecologylab/oodss/distributed/common/ClientConstants.java b/simplCore/src/ecologylab/oodss/distributed/common/ClientConstants.java index 4fad761a..00f9e72c 100644 --- a/simplCore/src/ecologylab/oodss/distributed/common/ClientConstants.java +++ b/simplCore/src/ecologylab/oodss/distributed/common/ClientConstants.java @@ -1,19 +1,19 @@ -/* - * Created on May 5, 2006 - */ -package ecologylab.oodss.distributed.common; - -/** - * Constant settings for client functionality. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public interface ClientConstants extends NetworkingConstants -{ - /** Number of reconnect attempts to make before giving up. */ - static final int RECONNECT_ATTEMPTS = 50; - - /** Number of milliseconds to sleep between attempts to reconnect. */ - static final int WAIT_BEWTEEN_RECONNECT_ATTEMPTS = 3000; -} +/* + * Created on May 5, 2006 + */ +package ecologylab.oodss.distributed.common; + +/** + * Constant settings for client functionality. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public interface ClientConstants extends NetworkingConstants +{ + /** Number of reconnect attempts to make before giving up. */ + static final int RECONNECT_ATTEMPTS = 50; + + /** Number of milliseconds to sleep between attempts to reconnect. */ + static final int WAIT_BEWTEEN_RECONNECT_ATTEMPTS = 3000; +} diff --git a/simplCore/src/ecologylab/oodss/distributed/common/LimitedInputStream.java b/simplCore/src/ecologylab/oodss/distributed/common/LimitedInputStream.java index 130b4993..f7ae7a01 100644 --- a/simplCore/src/ecologylab/oodss/distributed/common/LimitedInputStream.java +++ b/simplCore/src/ecologylab/oodss/distributed/common/LimitedInputStream.java @@ -1,122 +1,122 @@ -package ecologylab.oodss.distributed.common; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; - -public class LimitedInputStream extends FilterInputStream -{ - private int limit; - - private int left; - - public LimitedInputStream(InputStream in, int limit) - { - super(in); - this.limit = this.left = limit; - } - - @Override - public boolean markSupported() - { - return false; - } - - @Override - public int read(byte[] b, int off, int len) throws IOException - { - if(len > left) - { - len = left; - } - - int ret = this.in.read(b, off, len); - if(ret > 0) - { - left -= ret; - } - - return ret; - } - - @Override - public int read(byte[] b) throws IOException - { - if(b.length > left) - { - int ret = this.in.read(b, 0, left); - if(ret > 0) - { - left -= ret; - } - - return ret; - } - else - { - int ret = this.in.read(b); - if(ret > 0) - { - left -= ret; - } - return ret; - } - } - - @Override - public int read() throws IOException - { - int ret; - if(left > 0) - { - ret = this.in.read(); - if(ret >= 0) - { - left--; - } - } - else - { - ret = -1; - } - return ret; - } - - @Override - public int available() throws IOException - { - return Math.min(left, in.available()); - } - - @Override - public long skip(long n) throws IOException - { - long ret = 0; - - if(n > left) - { - ret = this.in.skip(left); - } - else - { - ret = this.in.skip(n); - } - - left -= ret; - - return ret; - } - - @Override - public void mark(int readLimit) - { - - } - - @Override - public void reset() - { - - } - -} +package ecologylab.oodss.distributed.common; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class LimitedInputStream extends FilterInputStream +{ + private int limit; + + private int left; + + public LimitedInputStream(InputStream in, int limit) + { + super(in); + this.limit = this.left = limit; + } + + @Override + public boolean markSupported() + { + return false; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException + { + if(len > left) + { + len = left; + } + + int ret = this.in.read(b, off, len); + if(ret > 0) + { + left -= ret; + } + + return ret; + } + + @Override + public int read(byte[] b) throws IOException + { + if(b.length > left) + { + int ret = this.in.read(b, 0, left); + if(ret > 0) + { + left -= ret; + } + + return ret; + } + else + { + int ret = this.in.read(b); + if(ret > 0) + { + left -= ret; + } + return ret; + } + } + + @Override + public int read() throws IOException + { + int ret; + if(left > 0) + { + ret = this.in.read(); + if(ret >= 0) + { + left--; + } + } + else + { + ret = -1; + } + return ret; + } + + @Override + public int available() throws IOException + { + return Math.min(left, in.available()); + } + + @Override + public long skip(long n) throws IOException + { + long ret = 0; + + if(n > left) + { + ret = this.in.skip(left); + } + else + { + ret = this.in.skip(n); + } + + left -= ret; + + return ret; + } + + @Override + public void mark(int readLimit) + { + + } + + @Override + public void reset() + { + + } + +} diff --git a/simplCore/src/ecologylab/oodss/distributed/common/NetworkingConstants.java b/simplCore/src/ecologylab/oodss/distributed/common/NetworkingConstants.java index 6f01697a..7f5ea363 100644 --- a/simplCore/src/ecologylab/oodss/distributed/common/NetworkingConstants.java +++ b/simplCore/src/ecologylab/oodss/distributed/common/NetworkingConstants.java @@ -1,53 +1,53 @@ -/** - * - */ -package ecologylab.oodss.distributed.common; - -import java.nio.charset.Charset; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public interface NetworkingConstants -{ - /** the maximum size of message acceptable by server in encoded CHARs */ - static final int DEFAULT_MAX_MESSAGE_LENGTH_CHARS = 128 * 1024; // 128KB - - static final int DEFAULT_IDLE_TIMEOUT = 10000; - - /** The maximum size an http-like header on a message may be, in bytes. */ - static final int MAX_HTTP_HEADER_LENGTH = 4 * 1024; // 4KB - - /** The content-length http-like header indicator. */ - static final String CONTENT_LENGTH_STRING = "content-length"; - - static final String UNIQUE_IDENTIFIER_STRING = "uid"; - - static final String HTTP_HEADER_LINE_DELIMITER = "\r\n"; - - /** The terminator string for the end of http-like headers. */ - static final String HTTP_HEADER_TERMINATOR = HTTP_HEADER_LINE_DELIMITER - + HTTP_HEADER_LINE_DELIMITER; - - /** Content coding specifies whether or not to some type of comression is used in the message */ - static final String HTTP_CONTENT_CODING = "content-encoding"; - - /** Specifies what decoding schemes are acceptable to send back to the the client */ - static final String HTTP_ACCEPTED_ENCODINGS = "accept-encoding:deflate"; - - static final String HTTP_ACCEPT_ENCODING = "accept-encoding"; - - /** String specifying deflate encoding */ - static final String HTTP_DEFLATE_ENCODING = "deflate"; - - /** The size of the content-length header indicator. */ - static final int CONTENT_LENGTH_STRING_LENGTH = CONTENT_LENGTH_STRING.length(); - - /** Character encoding for messages sent through the network. */ - static final String CHARACTER_ENCODING = "ISO-8859-1"; - - /** Charset for CHARACTER_ENCODING; to avoid calling forName too much. */ - static final Charset CHARSET = Charset - .forName(CHARACTER_ENCODING); -} +/** + * + */ +package ecologylab.oodss.distributed.common; + +import java.nio.charset.Charset; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public interface NetworkingConstants +{ + /** the maximum size of message acceptable by server in encoded CHARs */ + static final int DEFAULT_MAX_MESSAGE_LENGTH_CHARS = 128 * 1024; // 128KB + + static final int DEFAULT_IDLE_TIMEOUT = 10000; + + /** The maximum size an http-like header on a message may be, in bytes. */ + static final int MAX_HTTP_HEADER_LENGTH = 4 * 1024; // 4KB + + /** The content-length http-like header indicator. */ + static final String CONTENT_LENGTH_STRING = "content-length"; + + static final String UNIQUE_IDENTIFIER_STRING = "uid"; + + static final String HTTP_HEADER_LINE_DELIMITER = "\r\n"; + + /** The terminator string for the end of http-like headers. */ + static final String HTTP_HEADER_TERMINATOR = HTTP_HEADER_LINE_DELIMITER + + HTTP_HEADER_LINE_DELIMITER; + + /** Content coding specifies whether or not to some type of comression is used in the message */ + static final String HTTP_CONTENT_CODING = "content-encoding"; + + /** Specifies what decoding schemes are acceptable to send back to the the client */ + static final String HTTP_ACCEPTED_ENCODINGS = "accept-encoding:deflate"; + + static final String HTTP_ACCEPT_ENCODING = "accept-encoding"; + + /** String specifying deflate encoding */ + static final String HTTP_DEFLATE_ENCODING = "deflate"; + + /** The size of the content-length header indicator. */ + static final int CONTENT_LENGTH_STRING_LENGTH = CONTENT_LENGTH_STRING.length(); + + /** Character encoding for messages sent through the network. */ + static final String CHARACTER_ENCODING = "ISO-8859-1"; + + /** Charset for CHARACTER_ENCODING; to avoid calling forName too much. */ + static final Charset CHARSET = Charset + .forName(CHARACTER_ENCODING); +} diff --git a/simplCore/src/ecologylab/oodss/distributed/common/ServerConstants.java b/simplCore/src/ecologylab/oodss/distributed/common/ServerConstants.java index 563a0ccc..19e963db 100644 --- a/simplCore/src/ecologylab/oodss/distributed/common/ServerConstants.java +++ b/simplCore/src/ecologylab/oodss/distributed/common/ServerConstants.java @@ -1,20 +1,20 @@ -/* - * Created on May 3, 2006 - */ -package ecologylab.oodss.distributed.common; - - -/** - * Constants used by ServicesServers and their components. - */ -public interface ServerConstants extends NetworkingConstants -{ - /** If we get more bad messages than this, it may be malicous. */ - static final int MAXIMUM_TRANSMISSION_ERRORS = 3; - - /** Limit the maximum number of client connection to the server */ - static final int MAX_CONNECTIONS = 100; - - /** Maximum amount of time, in milliseconds, a connection can be idle, even if we don't want to drop idle connections. */ - static final int GARBAGE_CONNECTION_CLEANUP_TIMEOUT = 8 * 60 * 60 * 1000; // 8 hours -} +/* + * Created on May 3, 2006 + */ +package ecologylab.oodss.distributed.common; + + +/** + * Constants used by ServicesServers and their components. + */ +public interface ServerConstants extends NetworkingConstants +{ + /** If we get more bad messages than this, it may be malicous. */ + static final int MAXIMUM_TRANSMISSION_ERRORS = 3; + + /** Limit the maximum number of client connection to the server */ + static final int MAX_CONNECTIONS = 100; + + /** Maximum amount of time, in milliseconds, a connection can be idle, even if we don't want to drop idle connections. */ + static final int GARBAGE_CONNECTION_CLEANUP_TIMEOUT = 8 * 60 * 60 * 1000; // 8 hours +} diff --git a/simplCore/src/ecologylab/oodss/distributed/common/ServicesHostsAndPorts.java b/simplCore/src/ecologylab/oodss/distributed/common/ServicesHostsAndPorts.java index 0b055ae2..035a0347 100644 --- a/simplCore/src/ecologylab/oodss/distributed/common/ServicesHostsAndPorts.java +++ b/simplCore/src/ecologylab/oodss/distributed/common/ServicesHostsAndPorts.java @@ -1,61 +1,61 @@ -/* - * Created on Apr 5, 2006 - */ -package ecologylab.oodss.distributed.common; - -/** - * A place to gather host and port assignments in the Interface Ecology Lab. People using our - * software elsewhere may wish to change these. People in our lab need to talk to each other about - * changes here. - * - * @author andruid - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public interface ServicesHostsAndPorts -{ - // public static final String LOGGING_HOST = "128.194.147.49"; // ecology1 - // publicstatic final String LOGGING_HOST = "128.194.138.51"; // - // unix.cs.tamu.edu - - /** The CSDLL host. */ - public static final String CSDLL_HOST = "128.194.147.58"; // CSDLL - - /** Normal place to look for a logging server; currently localhost. */ - public static final String LOGGING_HOST = "128.194.147.145"; // ecology0.cs.tamu.edu - - /** Normal port for handling remote logging. */ - public static final int LOGGING_PORT = 10201; - - /** Normal port for browser services. */ - public static final int BROWSER_SERVICES_PORT = 10001; - - /** Normal port for combinFormation services. */ - public static final int CF_SERVICES_PORT = 10010; - - /** Normal port for Rogue Signals network communication. */ - public static final int ROGUE_PORT = 2107; - - /** Normal port for Rogue Signals to communicate with sound patches. */ - public static final int ROGUE_OSC_SOUND_PATCH_LISTENER_PORT = 14446; - - /** Normal port for Rogue Signals to communicate with sound patches. */ - public static final int ROGUE_OSC_SOUND_RECORDER_ACKNOWLEDGE_PORT = 14450; - - /** - * Normal port that TTeCLoG uses to listen for VAD signals from its audio patch. - */ - public static final int ROGUE_OSC_VAD_PATCH = 14451; - - /** - * The transmission port for the client's radio simulator patch. Each client has to transmit on a - * different port, so this is the base, to which we add a seekers ord (order) value, or 3 if it is - * the coordinator. - */ - public static final int TTEC_RADIO_SIM_CLIENT_TRANSMIT_PORT_BASE = 8001; - - /** Normal port for Rogue Signals to communicate with physiological sensors. */ - public static final int PHYSI_ROGUE_UDP_PORT = 14445; - - /** Normal port for web application services. */ - public static final int WEB_START_APP_SERVICES_PORT = 10011; -} +/* + * Created on Apr 5, 2006 + */ +package ecologylab.oodss.distributed.common; + +/** + * A place to gather host and port assignments in the Interface Ecology Lab. People using our + * software elsewhere may wish to change these. People in our lab need to talk to each other about + * changes here. + * + * @author andruid + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public interface ServicesHostsAndPorts +{ + // public static final String LOGGING_HOST = "128.194.147.49"; // ecology1 + // publicstatic final String LOGGING_HOST = "128.194.138.51"; // + // unix.cs.tamu.edu + + /** The CSDLL host. */ + public static final String CSDLL_HOST = "128.194.147.58"; // CSDLL + + /** Normal place to look for a logging server; currently localhost. */ + public static final String LOGGING_HOST = "128.194.147.145"; // ecology0.cs.tamu.edu + + /** Normal port for handling remote logging. */ + public static final int LOGGING_PORT = 10201; + + /** Normal port for browser services. */ + public static final int BROWSER_SERVICES_PORT = 10001; + + /** Normal port for combinFormation services. */ + public static final int CF_SERVICES_PORT = 10010; + + /** Normal port for Rogue Signals network communication. */ + public static final int ROGUE_PORT = 2107; + + /** Normal port for Rogue Signals to communicate with sound patches. */ + public static final int ROGUE_OSC_SOUND_PATCH_LISTENER_PORT = 14446; + + /** Normal port for Rogue Signals to communicate with sound patches. */ + public static final int ROGUE_OSC_SOUND_RECORDER_ACKNOWLEDGE_PORT = 14450; + + /** + * Normal port that TTeCLoG uses to listen for VAD signals from its audio patch. + */ + public static final int ROGUE_OSC_VAD_PATCH = 14451; + + /** + * The transmission port for the client's radio simulator patch. Each client has to transmit on a + * different port, so this is the base, to which we add a seekers ord (order) value, or 3 if it is + * the coordinator. + */ + public static final int TTEC_RADIO_SIM_CLIENT_TRANSMIT_PORT_BASE = 8001; + + /** Normal port for Rogue Signals to communicate with physiological sensors. */ + public static final int PHYSI_ROGUE_UDP_PORT = 14445; + + /** Normal port for web application services. */ + public static final int WEB_START_APP_SERVICES_PORT = 10011; +} diff --git a/simplCore/src/ecologylab/oodss/distributed/common/SessionObjects.java b/simplCore/src/ecologylab/oodss/distributed/common/SessionObjects.java index 2780c096..ca40577f 100644 --- a/simplCore/src/ecologylab/oodss/distributed/common/SessionObjects.java +++ b/simplCore/src/ecologylab/oodss/distributed/common/SessionObjects.java @@ -1,48 +1,48 @@ -package ecologylab.oodss.distributed.common; - -import ecologylab.oodss.messages.DefaultServicesTranslations; -import ecologylab.serialization.SimplTypesScope; - -/** - * Constants that define general ecologylab objects that get stored in the - * Session ObjectRegistry. - * - * @author andruid - * - */ -public interface SessionObjects -{ - public static final String MAIN_START_AND_STOPPABLE = "main_start_and_stoppable"; - - public static final String MAIN_SHUTDOWNABLE = "main_shutdownable"; - - public static final SimplTypesScope BROWSER_SERVICES_TRANSLATIONS = DefaultServicesTranslations.get(); - /*TranslationScope - .get( - "Browse", - "ecologylab.oodss.messages"); */ - -// public static final String BROWSER_SERVICES_CLIENT = "browser_services_client"; - - public static final String LOGGING = "logging"; - - public static final String TOP_LEVEL = "top_level"; - - public static final String NAMED_STYLES_MAP = "named_styles_map"; - - public static final String INTEREST_MODEL_SOURCE = "interest_model_source"; - - public static final String GRAPHICS_CONFIGURATION = "graphics_configuration"; - - public static final String SESSIONS_MAP = "sessions_map"; - - public static final String SESSION_HANDLE = "SESSION_HANLDE"; - - public static final String APPLICATION_ENVIRONMENT = "application_environment"; - - public static final String SESSION_ID = "session_id"; - - public static final String SESSIONS_MAP_BY_SESSION_ID = "sessions_map_by_session_id"; - - public static final String OODSS_WEBSOCKET_SERVER = "oodss_websocket_server"; -} +package ecologylab.oodss.distributed.common; + +import ecologylab.oodss.messages.DefaultServicesTranslations; +import ecologylab.serialization.SimplTypesScope; + +/** + * Constants that define general ecologylab objects that get stored in the + * Session ObjectRegistry. + * + * @author andruid + * + */ +public interface SessionObjects +{ + public static final String MAIN_START_AND_STOPPABLE = "main_start_and_stoppable"; + + public static final String MAIN_SHUTDOWNABLE = "main_shutdownable"; + + public static final SimplTypesScope BROWSER_SERVICES_TRANSLATIONS = DefaultServicesTranslations.get(); + /*TranslationScope + .get( + "Browse", + "ecologylab.oodss.messages"); */ + +// public static final String BROWSER_SERVICES_CLIENT = "browser_services_client"; + + public static final String LOGGING = "logging"; + + public static final String TOP_LEVEL = "top_level"; + + public static final String NAMED_STYLES_MAP = "named_styles_map"; + + public static final String INTEREST_MODEL_SOURCE = "interest_model_source"; + + public static final String GRAPHICS_CONFIGURATION = "graphics_configuration"; + + public static final String SESSIONS_MAP = "sessions_map"; + + public static final String SESSION_HANDLE = "SESSION_HANLDE"; + + public static final String APPLICATION_ENVIRONMENT = "application_environment"; + + public static final String SESSION_ID = "session_id"; + + public static final String SESSIONS_MAP_BY_SESSION_ID = "sessions_map_by_session_id"; + + public static final String OODSS_WEBSOCKET_SERVER = "oodss_websocket_server"; +} diff --git a/simplCore/src/ecologylab/oodss/distributed/exception/MessageTooLargeException.java b/simplCore/src/ecologylab/oodss/distributed/exception/MessageTooLargeException.java index 92503c53..5f895000 100644 --- a/simplCore/src/ecologylab/oodss/distributed/exception/MessageTooLargeException.java +++ b/simplCore/src/ecologylab/oodss/distributed/exception/MessageTooLargeException.java @@ -1,75 +1,75 @@ -/** - * - */ -package ecologylab.oodss.distributed.exception; - -/** - * An exception that indicates that a message was too large; typically this - * means that a message to be sent from a client to a server is too large for - * the client's buffer and will likely be rejected by the server. - * - * @author Zachary O. Toups (toupsz@ecologylab.net) - */ -public class MessageTooLargeException extends Exception -{ - private static final long serialVersionUID = 1732834475978273620L; - - private int maxMessageSize; - - private int actualMessageSize; - - /** - * @return the maxMessageSize - */ - public int getMaxMessageSize() - { - return maxMessageSize; - } - - /** - * @return the actualMessageSize - */ - public int getActualMessageSize() - { - return actualMessageSize; - } - - /** - * - */ - public MessageTooLargeException(int maxMessageSize, int actualMessageSize) - { - this("", maxMessageSize, actualMessageSize); - } - - /** - * @param message - */ - public MessageTooLargeException(String message, int maxMessageSize, - int actualMessageSize) - { - super(message); - - this.maxMessageSize = maxMessageSize; - this.actualMessageSize = actualMessageSize; - } - - /** - * @param cause - */ - public MessageTooLargeException(Throwable cause) - { - super(cause); - } - - /** - * @param message - * @param cause - */ - public MessageTooLargeException(String message, Throwable cause) - { - super(message, cause); - // TODO Auto-generated constructor stub - } - -} +/** + * + */ +package ecologylab.oodss.distributed.exception; + +/** + * An exception that indicates that a message was too large; typically this + * means that a message to be sent from a client to a server is too large for + * the client's buffer and will likely be rejected by the server. + * + * @author Zachary O. Toups (toupsz@ecologylab.net) + */ +public class MessageTooLargeException extends Exception +{ + private static final long serialVersionUID = 1732834475978273620L; + + private int maxMessageSize; + + private int actualMessageSize; + + /** + * @return the maxMessageSize + */ + public int getMaxMessageSize() + { + return maxMessageSize; + } + + /** + * @return the actualMessageSize + */ + public int getActualMessageSize() + { + return actualMessageSize; + } + + /** + * + */ + public MessageTooLargeException(int maxMessageSize, int actualMessageSize) + { + this("", maxMessageSize, actualMessageSize); + } + + /** + * @param message + */ + public MessageTooLargeException(String message, int maxMessageSize, + int actualMessageSize) + { + super(message); + + this.maxMessageSize = maxMessageSize; + this.actualMessageSize = actualMessageSize; + } + + /** + * @param cause + */ + public MessageTooLargeException(Throwable cause) + { + super(cause); + } + + /** + * @param message + * @param cause + */ + public MessageTooLargeException(String message, Throwable cause) + { + super(message, cause); + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/oodss/distributed/impl/AbstractNIOServer.java b/simplCore/src/ecologylab/oodss/distributed/impl/AbstractNIOServer.java index 525a8903..01ba048e 100755 --- a/simplCore/src/ecologylab/oodss/distributed/impl/AbstractNIOServer.java +++ b/simplCore/src/ecologylab/oodss/distributed/impl/AbstractNIOServer.java @@ -1,165 +1,165 @@ -/** - * - */ -package ecologylab.oodss.distributed.impl; - -import java.io.IOException; -import java.net.BindException; -import java.net.InetAddress; -import java.nio.channels.SelectionKey; - -import ecologylab.collections.Scope; -import ecologylab.net.NetTools; -import ecologylab.oodss.distributed.common.SessionObjects; -import ecologylab.oodss.distributed.server.NIOServerDataReader; -import ecologylab.oodss.distributed.server.clientsessionmanager.BaseSessionManager; -import ecologylab.oodss.messages.InitConnectionRequest; -import ecologylab.serialization.SimplTypesScope; - -/** - * Provides access to an NIOServerIOThread, which handles the details of network connections. - * Subclasses extend and provide functionality for actually processing messages. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public abstract class AbstractNIOServer extends Manager implements - NIOServerDataReader, Runnable, SessionObjects -{ - private NIOServerIOThread backend; - - protected SimplTypesScope translationScope; - - protected S applicationObjectScope; - - /** - * Creates an instance of an NIOServer of some flavor. Creates the backend using the information - * in the arguments. - * - * Registers itself as the MAIN_START_AND_STOPPABLE in the object registry. - * - * @param portNumber - * @param inetAddress - * @param translationScope - * @param objectRegistry - * @throws IOException - * @throws BindException - */ - protected AbstractNIOServer(int portNumber, InetAddress[] inetAddress, - SimplTypesScope requestTranslationSpace, S objectRegistry, int idleConnectionTimeout, - int maxMessageLength) throws IOException, BindException - { - backend = this.generateBackend(portNumber, inetAddress, composeTranslations(portNumber, - inetAddress[0], requestTranslationSpace), objectRegistry, idleConnectionTimeout, - maxMessageLength); - - debug("setting up NIO Server..."); - - // we get these from the backend, because it ensures that they are - // configured if they are passed in null - this.translationScope = backend.translationScope; - this.applicationObjectScope = (S) backend.objectRegistry; - - this.applicationObjectScope.put(MAIN_START_AND_STOPPABLE, this); - this.applicationObjectScope.put(MAIN_SHUTDOWNABLE, this); - } - - static final Class[] OUR_TRANSLATIONS = - { InitConnectionRequest.class, }; - - public static SimplTypesScope composeTranslations(int portNumber, InetAddress inetAddress, - SimplTypesScope requestTranslationSpace) - { - return composeTranslations(OUR_TRANSLATIONS, "nio_server_base: ", portNumber, inetAddress - .toString(), requestTranslationSpace); - } - - public static SimplTypesScope composeTranslations(Class[] newTranslations, String prefix, - int portNumber, String inetAddress, SimplTypesScope requestTranslationSpace) - { - return SimplTypesScope.get(prefix + inetAddress.toString() + ":" + portNumber, - requestTranslationSpace, newTranslations); - } - - /** - * Creates an instance of an NIOServer of some flavor. Creates the backend using the information - * in the arguments. - * - * Registers itself as the MAIN_START_AND_STOPPABLE in the object registry. - * - * @param portNumber - * @param inetAddress - * @param translationScope - * @param objectRegistry - * @throws IOException - * @throws BindException - */ - protected AbstractNIOServer(int portNumber, InetAddress inetAddress, - SimplTypesScope requestTranslationSpace, S objectRegistry, int idleConnectionTimeout, - int maxMessageLength) throws IOException, BindException - { - this(portNumber, NetTools.wrapSingleAddress(inetAddress), requestTranslationSpace, - objectRegistry, idleConnectionTimeout, maxMessageLength); - } - - protected NIOServerIOThread generateBackend(int portNumber, InetAddress[] inetAddresses, - SimplTypesScope requestTranslationSpace, S objectRegistry, int idleConnectionTimeout, - int maxMessageLength) throws BindException, IOException - { - return NIOServerIOThread.getInstance(portNumber, inetAddresses, this, requestTranslationSpace, - objectRegistry, idleConnectionTimeout, maxMessageLength); - } - - protected abstract BaseSessionManager generateContextManager(String sessionId, SelectionKey sk, - SimplTypesScope translationScope, Scope globalScope); - - /** - * @see ecologylab.generic.StartAndStoppable#start() - */ - @Override - public void start() - { - try - { - backend.openSelector(); - backend.registerAcceptWithSelector(); - backend.start(); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - - /** - * @see ecologylab.generic.StartAndStoppable#stop() - */ - @Override - public void stop() - { - backend.stop(); - } - - /** - * @return the backend - */ - public NIOServerIOThread getBackend() - { - return backend; - } - - /** - * @return the global scope for this server - */ - public Scope getGlobalScope() - { - return applicationObjectScope; - } - - /** - * @return the translationScope - */ - public SimplTypesScope getTranslationSpace() - { - return translationScope; - } -} +/** + * + */ +package ecologylab.oodss.distributed.impl; + +import java.io.IOException; +import java.net.BindException; +import java.net.InetAddress; +import java.nio.channels.SelectionKey; + +import ecologylab.collections.Scope; +import ecologylab.net.NetTools; +import ecologylab.oodss.distributed.common.SessionObjects; +import ecologylab.oodss.distributed.server.NIOServerDataReader; +import ecologylab.oodss.distributed.server.clientsessionmanager.BaseSessionManager; +import ecologylab.oodss.messages.InitConnectionRequest; +import ecologylab.serialization.SimplTypesScope; + +/** + * Provides access to an NIOServerIOThread, which handles the details of network connections. + * Subclasses extend and provide functionality for actually processing messages. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public abstract class AbstractNIOServer extends Manager implements + NIOServerDataReader, Runnable, SessionObjects +{ + private NIOServerIOThread backend; + + protected SimplTypesScope translationScope; + + protected S applicationObjectScope; + + /** + * Creates an instance of an NIOServer of some flavor. Creates the backend using the information + * in the arguments. + * + * Registers itself as the MAIN_START_AND_STOPPABLE in the object registry. + * + * @param portNumber + * @param inetAddress + * @param translationScope + * @param objectRegistry + * @throws IOException + * @throws BindException + */ + protected AbstractNIOServer(int portNumber, InetAddress[] inetAddress, + SimplTypesScope requestTranslationSpace, S objectRegistry, int idleConnectionTimeout, + int maxMessageLength) throws IOException, BindException + { + backend = this.generateBackend(portNumber, inetAddress, composeTranslations(portNumber, + inetAddress[0], requestTranslationSpace), objectRegistry, idleConnectionTimeout, + maxMessageLength); + + debug("setting up NIO Server..."); + + // we get these from the backend, because it ensures that they are + // configured if they are passed in null + this.translationScope = backend.translationScope; + this.applicationObjectScope = (S) backend.objectRegistry; + + this.applicationObjectScope.put(MAIN_START_AND_STOPPABLE, this); + this.applicationObjectScope.put(MAIN_SHUTDOWNABLE, this); + } + + static final Class[] OUR_TRANSLATIONS = + { InitConnectionRequest.class, }; + + public static SimplTypesScope composeTranslations(int portNumber, InetAddress inetAddress, + SimplTypesScope requestTranslationSpace) + { + return composeTranslations(OUR_TRANSLATIONS, "nio_server_base: ", portNumber, inetAddress + .toString(), requestTranslationSpace); + } + + public static SimplTypesScope composeTranslations(Class[] newTranslations, String prefix, + int portNumber, String inetAddress, SimplTypesScope requestTranslationSpace) + { + return SimplTypesScope.get(prefix + inetAddress.toString() + ":" + portNumber, + requestTranslationSpace, newTranslations); + } + + /** + * Creates an instance of an NIOServer of some flavor. Creates the backend using the information + * in the arguments. + * + * Registers itself as the MAIN_START_AND_STOPPABLE in the object registry. + * + * @param portNumber + * @param inetAddress + * @param translationScope + * @param objectRegistry + * @throws IOException + * @throws BindException + */ + protected AbstractNIOServer(int portNumber, InetAddress inetAddress, + SimplTypesScope requestTranslationSpace, S objectRegistry, int idleConnectionTimeout, + int maxMessageLength) throws IOException, BindException + { + this(portNumber, NetTools.wrapSingleAddress(inetAddress), requestTranslationSpace, + objectRegistry, idleConnectionTimeout, maxMessageLength); + } + + protected NIOServerIOThread generateBackend(int portNumber, InetAddress[] inetAddresses, + SimplTypesScope requestTranslationSpace, S objectRegistry, int idleConnectionTimeout, + int maxMessageLength) throws BindException, IOException + { + return NIOServerIOThread.getInstance(portNumber, inetAddresses, this, requestTranslationSpace, + objectRegistry, idleConnectionTimeout, maxMessageLength); + } + + protected abstract BaseSessionManager generateContextManager(String sessionId, SelectionKey sk, + SimplTypesScope translationScope, Scope globalScope); + + /** + * @see ecologylab.generic.StartAndStoppable#start() + */ + @Override + public void start() + { + try + { + backend.openSelector(); + backend.registerAcceptWithSelector(); + backend.start(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + /** + * @see ecologylab.generic.StartAndStoppable#stop() + */ + @Override + public void stop() + { + backend.stop(); + } + + /** + * @return the backend + */ + public NIOServerIOThread getBackend() + { + return backend; + } + + /** + * @return the global scope for this server + */ + public Scope getGlobalScope() + { + return applicationObjectScope; + } + + /** + * @return the translationScope + */ + public SimplTypesScope getTranslationSpace() + { + return translationScope; + } +} diff --git a/simplCore/src/ecologylab/oodss/distributed/impl/MessageWithMetadata.java b/simplCore/src/ecologylab/oodss/distributed/impl/MessageWithMetadata.java index 6f275deb..f88556e4 100644 --- a/simplCore/src/ecologylab/oodss/distributed/impl/MessageWithMetadata.java +++ b/simplCore/src/ecologylab/oodss/distributed/impl/MessageWithMetadata.java @@ -1,116 +1,116 @@ -/* - * Created on Apr 4, 2007 - */ -package ecologylab.oodss.distributed.impl; - -import ecologylab.oodss.messages.ServiceMessage; - -/** - * Represents a RequestMessage that has been translated to XML. This object encapsulates the XML - * String, along with the request's UID, SID, and a user specified Attachment; - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * @author Bill Hamilton (bill@ecologylab.net) - */ -// FIXME -- Can we use StringBuilders in here directly to utilize memory better -public class MessageWithMetadata implements - Comparable> -{ - private long uid; - - private M message = null; - - private A attachment = null; - - /** - * - */ - public MessageWithMetadata(M response, long uid, A attachment) - { - this(); - - this.uid = uid; - - this.attachment = attachment; - - this.setMessage(response); - } - - public MessageWithMetadata(M response, long uid) - { - this(response, uid, null); - } - - public MessageWithMetadata(M response) - { - this(response, -1, null); - } - - public MessageWithMetadata() - { - - } - - /** - * Resets this for re-use. - */ - public void clear() - { - this.uid = -1; - this.message = null; - this.attachment = null; - } - - /** - * @return the request - */ - public M getMessage() - { - return message; - } - - public void setMessage(M response) - { - this.message = response; - } - - /** - * @return the uid - */ - public long getUid() - { - return uid; - } - - /** - * @return the attachment - */ - public A getAttachment() - { - return this.attachment; - } - - @Override - public int compareTo(MessageWithMetadata arg0) - { - return (int) (this.uid - arg0.getUid()); - } - - /** - * @param uid - * the uid to set - */ - public void setUid(long uid) - { - this.uid = uid; - } - - /** - * @param attachment - * the attachment to set - */ - public void setAttachment(A attachment) - { - this.attachment = attachment; - } -} +/* + * Created on Apr 4, 2007 + */ +package ecologylab.oodss.distributed.impl; + +import ecologylab.oodss.messages.ServiceMessage; + +/** + * Represents a RequestMessage that has been translated to XML. This object encapsulates the XML + * String, along with the request's UID, SID, and a user specified Attachment; + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * @author Bill Hamilton (bill@ecologylab.net) + */ +// FIXME -- Can we use StringBuilders in here directly to utilize memory better +public class MessageWithMetadata implements + Comparable> +{ + private long uid; + + private M message = null; + + private A attachment = null; + + /** + * + */ + public MessageWithMetadata(M response, long uid, A attachment) + { + this(); + + this.uid = uid; + + this.attachment = attachment; + + this.setMessage(response); + } + + public MessageWithMetadata(M response, long uid) + { + this(response, uid, null); + } + + public MessageWithMetadata(M response) + { + this(response, -1, null); + } + + public MessageWithMetadata() + { + + } + + /** + * Resets this for re-use. + */ + public void clear() + { + this.uid = -1; + this.message = null; + this.attachment = null; + } + + /** + * @return the request + */ + public M getMessage() + { + return message; + } + + public void setMessage(M response) + { + this.message = response; + } + + /** + * @return the uid + */ + public long getUid() + { + return uid; + } + + /** + * @return the attachment + */ + public A getAttachment() + { + return this.attachment; + } + + @Override + public int compareTo(MessageWithMetadata arg0) + { + return (int) (this.uid - arg0.getUid()); + } + + /** + * @param uid + * the uid to set + */ + public void setUid(long uid) + { + this.uid = uid; + } + + /** + * @param attachment + * the attachment to set + */ + public void setAttachment(A attachment) + { + this.attachment = attachment; + } +} diff --git a/simplCore/src/ecologylab/oodss/distributed/impl/MessageWithMetadataPool.java b/simplCore/src/ecologylab/oodss/distributed/impl/MessageWithMetadataPool.java index 2a2c273e..fd52bedd 100644 --- a/simplCore/src/ecologylab/oodss/distributed/impl/MessageWithMetadataPool.java +++ b/simplCore/src/ecologylab/oodss/distributed/impl/MessageWithMetadataPool.java @@ -1,42 +1,42 @@ -/** - * - */ -package ecologylab.oodss.distributed.impl; - -import ecologylab.generic.ResourcePool; -import ecologylab.oodss.messages.ServiceMessage; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class MessageWithMetadataPool extends ResourcePool> -{ - - /** - * @param initialPoolSize - * @param minimumPoolSize - * @param resourceObjectCapacity - */ - public MessageWithMetadataPool(int initialPoolSize, int minimumPoolSize) - { - super(initialPoolSize, minimumPoolSize); - } - - /** - * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) - */ - @Override protected void clean(MessageWithMetadata objectToClean) - { - objectToClean.clear(); - } - - /** - * @see ecologylab.generic.ResourcePool#generateNewResource() - */ - @Override protected MessageWithMetadata generateNewResource() - { - return new MessageWithMetadata(); - } - -} +/** + * + */ +package ecologylab.oodss.distributed.impl; + +import ecologylab.generic.ResourcePool; +import ecologylab.oodss.messages.ServiceMessage; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class MessageWithMetadataPool extends ResourcePool> +{ + + /** + * @param initialPoolSize + * @param minimumPoolSize + * @param resourceObjectCapacity + */ + public MessageWithMetadataPool(int initialPoolSize, int minimumPoolSize) + { + super(initialPoolSize, minimumPoolSize); + } + + /** + * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) + */ + @Override protected void clean(MessageWithMetadata objectToClean) + { + objectToClean.clear(); + } + + /** + * @see ecologylab.generic.ResourcePool#generateNewResource() + */ + @Override protected MessageWithMetadata generateNewResource() + { + return new MessageWithMetadata(); + } + +} diff --git a/simplCore/src/ecologylab/oodss/distributed/impl/NIOCore.java b/simplCore/src/ecologylab/oodss/distributed/impl/NIOCore.java index cff78dcf..205957cc 100644 --- a/simplCore/src/ecologylab/oodss/distributed/impl/NIOCore.java +++ b/simplCore/src/ecologylab/oodss/distributed/impl/NIOCore.java @@ -1,593 +1,593 @@ -/** - * - */ -package ecologylab.oodss.distributed.impl; - -import java.io.IOException; -import java.nio.channels.CancelledKeyException; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.SocketChannel; -import java.util.Iterator; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; - -import ecologylab.generic.Debug; -import ecologylab.generic.ResourcePool; -import ecologylab.generic.StartAndStoppable; -import ecologylab.oodss.distributed.common.NetworkingConstants; -import ecologylab.oodss.exceptions.BadClientException; -import ecologylab.oodss.exceptions.ClientOfflineException; - -/** - * Provides core functionality for NIO-based servers or clients. This class is Runnable and - * StartAndStoppable; it's run method automatically handles interest-switching on a selector's keys, - * as well as calling appropriate abstract methods whenever interest ops are selected. - * - * Subclasses are required to configure their own selector. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public abstract class NIOCore extends Debug implements StartAndStoppable, NetworkingConstants -{ - private Queue pendingSelectionOpChanges = new ConcurrentLinkedQueue(); - - protected Selector selector; - - private String networkingIdentifier = "NIOCore"; - - private volatile boolean running; - - private Thread thread; - - protected int portNumber; - - private SocketModeChangeRequestPool mReqPool = new SocketModeChangeRequestPool( - 20, 10); - - /** - * Instantiates a new NIOCore object. - * - * @param networkingIdentifier - * the name to identify this object when its thread is created. - * @param portNumber - * the port number that this object will use for network communications. - * @throws IOException - * if an I/O error occurs while trying to open a Selector from the system. - */ - protected NIOCore(String networkingIdentifier, int portNumber) throws IOException - { - this.networkingIdentifier = networkingIdentifier; - this.portNumber = portNumber; - } - - /** - * THIS METHOD SHOULD NOT BE CALLED DIRECTLY! - * - * Proper use of this method is through the start / stop methods. - * - * Main run method. Performs a loop of changing the mode (read/write) for each socket, if - * requested, then checks for and performs appropriate I/O for each socket that is ready. Ends - * when running is set to false (through the stop method). - * - * @see java.lang.Runnable#run() - */ - @Override - public final void run() - { - while (running) - { - // update pending selection operation changes - //synchronized (this.pendingSelectionOpChanges) - { - for (SocketModeChangeRequest changeReq : pendingSelectionOpChanges) - { - if (changeReq.key.channel().isRegistered()) - { - /* - * Perform any changes to the interest ops on the keys, before selecting. - */ - switch (changeReq.type) - { - case CHANGEOPS: - try - { - changeReq.key.interestOps(changeReq.ops); - } - catch (CancelledKeyException e) - { - debug("tried to change ops after key was cancelled."); - } - catch (IllegalArgumentException e1) - { - debug("illegal argument for interestOps: " + changeReq.ops); - } - break; - case INVALIDATE_PERMANENTLY: - debug(">>>>>>>>>>>>>>>> invalidating permanently: " + changeReq.key.attachment()); - invalidateKey(changeReq.key, true); - break; - case INVALIDATE_TEMPORARILY: - debug(">>>>>>>>>>>>>>>> invalidating temporarily: " + changeReq.key.attachment()); - invalidateKey(changeReq.key, false); - break; - } - } - - // release the SocketModeChangeRequest when done - changeReq = this.mReqPool.release(changeReq); - } - - this.pendingSelectionOpChanges.clear(); - } - - // check selection operations - try - { - if (selector.select() > 0) - { - /* - * get an iterator of the keys that have something to do we have to do it this way, - * because we have to be able to call remove() which will not work in a foreach loop - */ - Iterator selectedKeyIter = selector.selectedKeys().iterator(); - - while (selectedKeyIter.hasNext()) - { - /* - * get the key corresponding to the event and process it appropriately, then remove it - */ - SelectionKey key = selectedKeyIter.next(); - - selectedKeyIter.remove(); - - if (!key.isValid()) - { - debug("invalid key"); - setPendingInvalidate(key, false); - } - else if (key.isReadable()) - { - /* - * incoming readable, valid key; have to double-check validity here, because accept - * key may have rejected an incoming connection - */ - if (key.channel().isOpen() && key.isValid()) - { - try - { - readReady(key); - readFinished(key); - } - catch (ClientOfflineException e) - { - warning(e.getMessage()); - setPendingInvalidate(key, false); - } - catch (BadClientException e) - { - // close down this evil connection! - error(e.getMessage()); - this.removeBadConnections(key); - } - catch (java.lang.IllegalArgumentException e) - { - warning(e.getMessage()); - } - } - else - { - debug("Channel closed on " + key.attachment() + ", removing."); - invalidateKey(key, false); - } - } - else if (key.isWritable()) - { - try - { - writeReady(key); - writeFinished(key); - } - catch (IOException e) - { - debug("IO error when attempting to write to socket; stack trace follows."); - - e.printStackTrace(); - } - - } - else if (key.isAcceptable()) - { // incoming connection; accept - this.acceptReady(key); - this.acceptFinished(key); - } - else if (key.isConnectable()) - { - this.connectReady(key); - this.connectFinished(key); - } - } - } - } - catch (IOException e) - { - this.stop(); - - debug("attempted to access selector after it was closed! shutting down"); - - e.printStackTrace(); - } - - // remove any that were idle for too long - this.checkAndDropIdleKeys(); - } - - this.close(); - } - - public void setPriority(int priority) - { - Thread thread = this.thread; - if (thread != null) - { - thread.setPriority(priority); - } - } - - /** - * @param key - */ - protected abstract void acceptReady(SelectionKey key); - - /** - * @param key - */ - protected abstract void connectReady(SelectionKey key); - - /** - * @param key - */ - protected abstract void readFinished(SelectionKey key); - - /** - * @param key - */ - protected abstract void readReady(SelectionKey key) throws ClientOfflineException, - BadClientException; - - /** - * Queues a request to change key's interest operations back to READ. - * - * This method is automatically called after acceptReady(SelectionKey) in the main operating loop. - * - * @param key - */ - public abstract void acceptFinished(SelectionKey key); - - /** - * Queues a request to change key's interest operations back to READ. - * - * This method is automatically called after connectReady(SelectionKey) in the main operating - * loop. - * - * @param key - */ - public void connectFinished(SelectionKey key) - { - this.queueForRead(key); - - selector.wakeup(); - } - - /** - * Queues a request to change key's interest operations back to READ. - * - * This method is automatically called after writeReady(SelectionKey) in the main operating loop. - * - * Perform any actions necessary after all data has been written from the outgoing queue to the - * client for this key. This is a hook method so that subclasses can provide specific - * functionality (such as, for example, invalidating the connection once the data has been sent. - * - * @param key - * - the SelectionKey that is finished writing. - */ - protected void writeFinished(SelectionKey key) - { - this.queueForRead(key); - - selector.wakeup(); - } - - protected abstract void removeBadConnections(SelectionKey key); - - /** - * Sets up a pending invalidate command for the given input. - * - * @param key - * the key to invalidate - * @param forcePermanent - * ignore any settings for the client and invalidate permanently no matter what - */ - public void setPendingInvalidate(SelectionKey key, boolean forcePermanent) - { - // allow subclass processing of the key being invalidated, and find out if - // it should be permanent - boolean permanent = this.handleInvalidate(key, forcePermanent); - - SocketModeChangeRequest req = this.mReqPool.acquire(); - req.key = key; - req.type = ((forcePermanent ? true : permanent) ? SocketModeChangeRequestType.INVALIDATE_PERMANENTLY - : SocketModeChangeRequestType.INVALIDATE_TEMPORARILY); - - //synchronized (pendingSelectionOpChanges) - { - this.pendingSelectionOpChanges.offer(req); - } - - selector.wakeup(); - } - - /** - * Checks the key to see what type of invalidation it should be (permanent, or temporary) and - * handles any housecleaning associated with invalidating that key. - * - * @param key - * - the key - * @param forcePermanent - * @return true if the key should be invalidated permanently, or false otherwise - */ - protected abstract boolean handleInvalidate(SelectionKey key, boolean forcePermanent); - - /** - * Shut down the connection associated with this SelectionKey. Subclasses should override to do - * your own housekeeping, then call super.invalidateKey(SelectionKey) to utilize the functionality - * here. - * - * @param chan - * The SocketChannel that needs to be shut down. - */ - protected void invalidateKey(SocketChannel chan) - { - try - { - chan.close(); - } - catch (IOException e) - { - debug(e.getMessage()); - } - catch (NullPointerException e) - { - debug(e.getMessage()); - } - - if (chan.keyFor(selector) != null) - { /* - * it's possible that they key was somehow disposed of already, perhaps it was already - * invalidated once - */ - chan.keyFor(selector).cancel(); - } - } - - /** - * @see ecologylab.oodss.distributed.impl.NIONetworking#invalidateKey(java.nio.channels.SocketChannel, - * boolean) - */ - protected abstract void invalidateKey(SelectionKey key, boolean permanent); - - @Override - public void start() - { - // start the server running - running = true; - - if (thread == null) - { - thread = new Thread(this, networkingIdentifier + " running on port " + portNumber); - synchronized (thread) - { - thread.start(); - } - } - - - } - - protected void openSelector() throws IOException - { - selector = Selector.open(); - } - - @Override - public synchronized void stop() - { - running = false; - - try - { - this.selector.wakeup(); - } - catch (Exception e) - { - e.printStackTrace(); - } - this.close(); - - if (thread != null) - { - synchronized (thread) - { // we cannot re-use the Thread object. - thread = null; - } - } - } - - protected void close() - { - } - - /** - * Check for timeout on all allocated keys; deallocate those that are hanging around, but no - * longer in use. - */ - protected abstract void checkAndDropIdleKeys(); - - /** - * @param key - */ - protected abstract void writeReady(SelectionKey key) throws IOException; - - protected void queueForAccept(SelectionKey key) - { - SocketModeChangeRequest req = this.mReqPool.acquire(); - req.key = key; - req.type = SocketModeChangeRequestType.CHANGEOPS; - req.ops = SelectionKey.OP_ACCEPT; - - //synchronized (this.pendingSelectionOpChanges) - { - // queue the socket channel for writing - this.pendingSelectionOpChanges.offer(req); - } - } - - protected void queueForConnect(SelectionKey key) - { - SocketModeChangeRequest req = this.mReqPool.acquire(); - req.key = key; - req.type = SocketModeChangeRequestType.CHANGEOPS; - req.ops = SelectionKey.OP_CONNECT; - - //synchronized (this.pendingSelectionOpChanges) - { - // queue the socket channel for writing - this.pendingSelectionOpChanges.offer(req); - } - } - - protected void queueForRead(SelectionKey key) - { - SocketModeChangeRequest req = this.mReqPool.acquire(); - req.key = key; - req.type = SocketModeChangeRequestType.CHANGEOPS; - req.ops = SelectionKey.OP_READ; - - //synchronized (this.pendingSelectionOpChanges) - { - // queue the socket channel for writing - this.pendingSelectionOpChanges.offer(req); - } - } - - protected void queueForWrite(SelectionKey key) - { - SocketModeChangeRequest req = this.mReqPool.acquire(); - req.key = key; - req.type = SocketModeChangeRequestType.CHANGEOPS; - req.ops = SelectionKey.OP_WRITE; - - //synchronized (this.pendingSelectionOpChanges) - { - // queue the socket channel for writing - this.pendingSelectionOpChanges.offer(req); - } - } - - /** - * @return the port number the server is listening on. - */ - public int getPortNumber() - { - return portNumber; - } - - protected enum SocketModeChangeRequestType - { - /** - * Indicates that the socket mode should not actually be changed; only used for fresh - * SocketModeChangeRequests that have not yet been specified. - */ - NONE, - - /** - * Indicates that the socket mode should change it's interest ops to those specified by the - * SocketModeChangeRequest. - */ - CHANGEOPS, - - /** - * Indicates that the socket should be permanently invalidated and it's matching client manager - * should be destroyed. This should only happen when clients purposefully disconnect or when - * they have been banned. Some special servers (such as HTTP servers) may also invalidate - * permanently when the socket disconnects. - */ - INVALIDATE_PERMANENTLY, - - /** - * Indicates that the socket should be temporarily disconnected. This results from an unexpected - * disconnect by the client. The result is that the matching client manager should be retained - * for some period of time, so that the client can reconnect if desired. - */ - INVALIDATE_TEMPORARILY - } - - /** - * A signaling object for modifying interest ops and socket invalidation in a thread-safe way. - * - * @author James Greenfield - */ - class SocketModeChangeRequest - { - public SelectionKey key; - - public SocketModeChangeRequestType type; - - public int ops; - - public SocketModeChangeRequest(SelectionKey key, SocketModeChangeRequestType type, int ops) - { - this.key = key; - this.type = type; - this.ops = ops; - } - } - - /** - * A resource pool that handles socket mode change requests to prevent unnecessary instantiations. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ - class SocketModeChangeRequestPool extends ResourcePool - { - /** - * @param initialPoolSize - * @param minimumPoolSize - */ - public SocketModeChangeRequestPool(int initialPoolSize, int minimumPoolSize) - { - super(initialPoolSize, minimumPoolSize); - } - - /** - * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) - */ - @Override - protected void clean(SocketModeChangeRequest objectToClean) - { - objectToClean.key = null; - objectToClean.ops = 0; - objectToClean.type = SocketModeChangeRequestType.NONE; - } - - /** - * @see ecologylab.generic.ResourcePool#generateNewResource() - */ - @Override - protected SocketModeChangeRequest generateNewResource() - { - return new SocketModeChangeRequest(null, SocketModeChangeRequestType.NONE, 0); - } - } -} +/** + * + */ +package ecologylab.oodss.distributed.impl; + +import java.io.IOException; +import java.nio.channels.CancelledKeyException; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; +import java.util.Iterator; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +import ecologylab.generic.Debug; +import ecologylab.generic.ResourcePool; +import ecologylab.generic.StartAndStoppable; +import ecologylab.oodss.distributed.common.NetworkingConstants; +import ecologylab.oodss.exceptions.BadClientException; +import ecologylab.oodss.exceptions.ClientOfflineException; + +/** + * Provides core functionality for NIO-based servers or clients. This class is Runnable and + * StartAndStoppable; it's run method automatically handles interest-switching on a selector's keys, + * as well as calling appropriate abstract methods whenever interest ops are selected. + * + * Subclasses are required to configure their own selector. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public abstract class NIOCore extends Debug implements StartAndStoppable, NetworkingConstants +{ + private Queue pendingSelectionOpChanges = new ConcurrentLinkedQueue(); + + protected Selector selector; + + private String networkingIdentifier = "NIOCore"; + + private volatile boolean running; + + private Thread thread; + + protected int portNumber; + + private SocketModeChangeRequestPool mReqPool = new SocketModeChangeRequestPool( + 20, 10); + + /** + * Instantiates a new NIOCore object. + * + * @param networkingIdentifier + * the name to identify this object when its thread is created. + * @param portNumber + * the port number that this object will use for network communications. + * @throws IOException + * if an I/O error occurs while trying to open a Selector from the system. + */ + protected NIOCore(String networkingIdentifier, int portNumber) throws IOException + { + this.networkingIdentifier = networkingIdentifier; + this.portNumber = portNumber; + } + + /** + * THIS METHOD SHOULD NOT BE CALLED DIRECTLY! + * + * Proper use of this method is through the start / stop methods. + * + * Main run method. Performs a loop of changing the mode (read/write) for each socket, if + * requested, then checks for and performs appropriate I/O for each socket that is ready. Ends + * when running is set to false (through the stop method). + * + * @see java.lang.Runnable#run() + */ + @Override + public final void run() + { + while (running) + { + // update pending selection operation changes + //synchronized (this.pendingSelectionOpChanges) + { + for (SocketModeChangeRequest changeReq : pendingSelectionOpChanges) + { + if (changeReq.key.channel().isRegistered()) + { + /* + * Perform any changes to the interest ops on the keys, before selecting. + */ + switch (changeReq.type) + { + case CHANGEOPS: + try + { + changeReq.key.interestOps(changeReq.ops); + } + catch (CancelledKeyException e) + { + debug("tried to change ops after key was cancelled."); + } + catch (IllegalArgumentException e1) + { + debug("illegal argument for interestOps: " + changeReq.ops); + } + break; + case INVALIDATE_PERMANENTLY: + debug(">>>>>>>>>>>>>>>> invalidating permanently: " + changeReq.key.attachment()); + invalidateKey(changeReq.key, true); + break; + case INVALIDATE_TEMPORARILY: + debug(">>>>>>>>>>>>>>>> invalidating temporarily: " + changeReq.key.attachment()); + invalidateKey(changeReq.key, false); + break; + } + } + + // release the SocketModeChangeRequest when done + changeReq = this.mReqPool.release(changeReq); + } + + this.pendingSelectionOpChanges.clear(); + } + + // check selection operations + try + { + if (selector.select() > 0) + { + /* + * get an iterator of the keys that have something to do we have to do it this way, + * because we have to be able to call remove() which will not work in a foreach loop + */ + Iterator selectedKeyIter = selector.selectedKeys().iterator(); + + while (selectedKeyIter.hasNext()) + { + /* + * get the key corresponding to the event and process it appropriately, then remove it + */ + SelectionKey key = selectedKeyIter.next(); + + selectedKeyIter.remove(); + + if (!key.isValid()) + { + debug("invalid key"); + setPendingInvalidate(key, false); + } + else if (key.isReadable()) + { + /* + * incoming readable, valid key; have to double-check validity here, because accept + * key may have rejected an incoming connection + */ + if (key.channel().isOpen() && key.isValid()) + { + try + { + readReady(key); + readFinished(key); + } + catch (ClientOfflineException e) + { + warning(e.getMessage()); + setPendingInvalidate(key, false); + } + catch (BadClientException e) + { + // close down this evil connection! + error(e.getMessage()); + this.removeBadConnections(key); + } + catch (java.lang.IllegalArgumentException e) + { + warning(e.getMessage()); + } + } + else + { + debug("Channel closed on " + key.attachment() + ", removing."); + invalidateKey(key, false); + } + } + else if (key.isWritable()) + { + try + { + writeReady(key); + writeFinished(key); + } + catch (IOException e) + { + debug("IO error when attempting to write to socket; stack trace follows."); + + e.printStackTrace(); + } + + } + else if (key.isAcceptable()) + { // incoming connection; accept + this.acceptReady(key); + this.acceptFinished(key); + } + else if (key.isConnectable()) + { + this.connectReady(key); + this.connectFinished(key); + } + } + } + } + catch (IOException e) + { + this.stop(); + + debug("attempted to access selector after it was closed! shutting down"); + + e.printStackTrace(); + } + + // remove any that were idle for too long + this.checkAndDropIdleKeys(); + } + + this.close(); + } + + public void setPriority(int priority) + { + Thread thread = this.thread; + if (thread != null) + { + thread.setPriority(priority); + } + } + + /** + * @param key + */ + protected abstract void acceptReady(SelectionKey key); + + /** + * @param key + */ + protected abstract void connectReady(SelectionKey key); + + /** + * @param key + */ + protected abstract void readFinished(SelectionKey key); + + /** + * @param key + */ + protected abstract void readReady(SelectionKey key) throws ClientOfflineException, + BadClientException; + + /** + * Queues a request to change key's interest operations back to READ. + * + * This method is automatically called after acceptReady(SelectionKey) in the main operating loop. + * + * @param key + */ + public abstract void acceptFinished(SelectionKey key); + + /** + * Queues a request to change key's interest operations back to READ. + * + * This method is automatically called after connectReady(SelectionKey) in the main operating + * loop. + * + * @param key + */ + public void connectFinished(SelectionKey key) + { + this.queueForRead(key); + + selector.wakeup(); + } + + /** + * Queues a request to change key's interest operations back to READ. + * + * This method is automatically called after writeReady(SelectionKey) in the main operating loop. + * + * Perform any actions necessary after all data has been written from the outgoing queue to the + * client for this key. This is a hook method so that subclasses can provide specific + * functionality (such as, for example, invalidating the connection once the data has been sent. + * + * @param key + * - the SelectionKey that is finished writing. + */ + protected void writeFinished(SelectionKey key) + { + this.queueForRead(key); + + selector.wakeup(); + } + + protected abstract void removeBadConnections(SelectionKey key); + + /** + * Sets up a pending invalidate command for the given input. + * + * @param key + * the key to invalidate + * @param forcePermanent + * ignore any settings for the client and invalidate permanently no matter what + */ + public void setPendingInvalidate(SelectionKey key, boolean forcePermanent) + { + // allow subclass processing of the key being invalidated, and find out if + // it should be permanent + boolean permanent = this.handleInvalidate(key, forcePermanent); + + SocketModeChangeRequest req = this.mReqPool.acquire(); + req.key = key; + req.type = ((forcePermanent ? true : permanent) ? SocketModeChangeRequestType.INVALIDATE_PERMANENTLY + : SocketModeChangeRequestType.INVALIDATE_TEMPORARILY); + + //synchronized (pendingSelectionOpChanges) + { + this.pendingSelectionOpChanges.offer(req); + } + + selector.wakeup(); + } + + /** + * Checks the key to see what type of invalidation it should be (permanent, or temporary) and + * handles any housecleaning associated with invalidating that key. + * + * @param key + * - the key + * @param forcePermanent + * @return true if the key should be invalidated permanently, or false otherwise + */ + protected abstract boolean handleInvalidate(SelectionKey key, boolean forcePermanent); + + /** + * Shut down the connection associated with this SelectionKey. Subclasses should override to do + * your own housekeeping, then call super.invalidateKey(SelectionKey) to utilize the functionality + * here. + * + * @param chan + * The SocketChannel that needs to be shut down. + */ + protected void invalidateKey(SocketChannel chan) + { + try + { + chan.close(); + } + catch (IOException e) + { + debug(e.getMessage()); + } + catch (NullPointerException e) + { + debug(e.getMessage()); + } + + if (chan.keyFor(selector) != null) + { /* + * it's possible that they key was somehow disposed of already, perhaps it was already + * invalidated once + */ + chan.keyFor(selector).cancel(); + } + } + + /** + * @see ecologylab.oodss.distributed.impl.NIONetworking#invalidateKey(java.nio.channels.SocketChannel, + * boolean) + */ + protected abstract void invalidateKey(SelectionKey key, boolean permanent); + + @Override + public void start() + { + // start the server running + running = true; + + if (thread == null) + { + thread = new Thread(this, networkingIdentifier + " running on port " + portNumber); + synchronized (thread) + { + thread.start(); + } + } + + + } + + protected void openSelector() throws IOException + { + selector = Selector.open(); + } + + @Override + public synchronized void stop() + { + running = false; + + try + { + this.selector.wakeup(); + } + catch (Exception e) + { + e.printStackTrace(); + } + this.close(); + + if (thread != null) + { + synchronized (thread) + { // we cannot re-use the Thread object. + thread = null; + } + } + } + + protected void close() + { + } + + /** + * Check for timeout on all allocated keys; deallocate those that are hanging around, but no + * longer in use. + */ + protected abstract void checkAndDropIdleKeys(); + + /** + * @param key + */ + protected abstract void writeReady(SelectionKey key) throws IOException; + + protected void queueForAccept(SelectionKey key) + { + SocketModeChangeRequest req = this.mReqPool.acquire(); + req.key = key; + req.type = SocketModeChangeRequestType.CHANGEOPS; + req.ops = SelectionKey.OP_ACCEPT; + + //synchronized (this.pendingSelectionOpChanges) + { + // queue the socket channel for writing + this.pendingSelectionOpChanges.offer(req); + } + } + + protected void queueForConnect(SelectionKey key) + { + SocketModeChangeRequest req = this.mReqPool.acquire(); + req.key = key; + req.type = SocketModeChangeRequestType.CHANGEOPS; + req.ops = SelectionKey.OP_CONNECT; + + //synchronized (this.pendingSelectionOpChanges) + { + // queue the socket channel for writing + this.pendingSelectionOpChanges.offer(req); + } + } + + protected void queueForRead(SelectionKey key) + { + SocketModeChangeRequest req = this.mReqPool.acquire(); + req.key = key; + req.type = SocketModeChangeRequestType.CHANGEOPS; + req.ops = SelectionKey.OP_READ; + + //synchronized (this.pendingSelectionOpChanges) + { + // queue the socket channel for writing + this.pendingSelectionOpChanges.offer(req); + } + } + + protected void queueForWrite(SelectionKey key) + { + SocketModeChangeRequest req = this.mReqPool.acquire(); + req.key = key; + req.type = SocketModeChangeRequestType.CHANGEOPS; + req.ops = SelectionKey.OP_WRITE; + + //synchronized (this.pendingSelectionOpChanges) + { + // queue the socket channel for writing + this.pendingSelectionOpChanges.offer(req); + } + } + + /** + * @return the port number the server is listening on. + */ + public int getPortNumber() + { + return portNumber; + } + + protected enum SocketModeChangeRequestType + { + /** + * Indicates that the socket mode should not actually be changed; only used for fresh + * SocketModeChangeRequests that have not yet been specified. + */ + NONE, + + /** + * Indicates that the socket mode should change it's interest ops to those specified by the + * SocketModeChangeRequest. + */ + CHANGEOPS, + + /** + * Indicates that the socket should be permanently invalidated and it's matching client manager + * should be destroyed. This should only happen when clients purposefully disconnect or when + * they have been banned. Some special servers (such as HTTP servers) may also invalidate + * permanently when the socket disconnects. + */ + INVALIDATE_PERMANENTLY, + + /** + * Indicates that the socket should be temporarily disconnected. This results from an unexpected + * disconnect by the client. The result is that the matching client manager should be retained + * for some period of time, so that the client can reconnect if desired. + */ + INVALIDATE_TEMPORARILY + } + + /** + * A signaling object for modifying interest ops and socket invalidation in a thread-safe way. + * + * @author James Greenfield + */ + class SocketModeChangeRequest + { + public SelectionKey key; + + public SocketModeChangeRequestType type; + + public int ops; + + public SocketModeChangeRequest(SelectionKey key, SocketModeChangeRequestType type, int ops) + { + this.key = key; + this.type = type; + this.ops = ops; + } + } + + /** + * A resource pool that handles socket mode change requests to prevent unnecessary instantiations. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ + class SocketModeChangeRequestPool extends ResourcePool + { + /** + * @param initialPoolSize + * @param minimumPoolSize + */ + public SocketModeChangeRequestPool(int initialPoolSize, int minimumPoolSize) + { + super(initialPoolSize, minimumPoolSize); + } + + /** + * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) + */ + @Override + protected void clean(SocketModeChangeRequest objectToClean) + { + objectToClean.key = null; + objectToClean.ops = 0; + objectToClean.type = SocketModeChangeRequestType.NONE; + } + + /** + * @see ecologylab.generic.ResourcePool#generateNewResource() + */ + @Override + protected SocketModeChangeRequest generateNewResource() + { + return new SocketModeChangeRequest(null, SocketModeChangeRequestType.NONE, 0); + } + } +} diff --git a/simplCore/src/ecologylab/oodss/distributed/impl/NIONetworking.java b/simplCore/src/ecologylab/oodss/distributed/impl/NIONetworking.java index 8b2bbf6d..34bfa405 100644 --- a/simplCore/src/ecologylab/oodss/distributed/impl/NIONetworking.java +++ b/simplCore/src/ecologylab/oodss/distributed/impl/NIONetworking.java @@ -1,284 +1,284 @@ -/* - * Created on Mar 2, 2007 - */ -package ecologylab.oodss.distributed.impl; - -import java.io.IOException; -import java.nio.BufferOverflowException; -import java.nio.ByteBuffer; -import java.nio.channels.SelectionKey; -import java.nio.channels.SocketChannel; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; -import java.util.Queue; - -import javax.naming.OperationNotSupportedException; - -import ecologylab.collections.Scope; -import ecologylab.io.ByteBufferPool; -import ecologylab.oodss.exceptions.BadClientException; -import ecologylab.oodss.exceptions.ClientOfflineException; -import ecologylab.oodss.messages.DefaultServicesTranslations; -import ecologylab.serialization.SimplTypesScope; - -/** - * Handles backend, low-level communication between distributed programs, using NIO. This is the - * basis for servers for handling network communication. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public abstract class NIONetworking extends NIOCore -{ - /** - * ByteBuffer that holds all incoming communication temporarily, immediately after it is read. - */ - private final ByteBuffer readBuffer; - - /** - * Maps SocketChannels (connections) to their write Queues of ByteBuffers. Whenever a - * SocketChannel is marked for writing, and comes up for writing, the server will write the set of - * ByteBuffers to the socket. - */ - private Map> pendingWrites = new HashMap>(); - - protected boolean shuttingDown = false; - - /** - * Space that defines mappings between xml names, and Java class names, for request messages. - */ - protected SimplTypesScope translationScope; - - /** Provides a context for request processing. */ - protected S objectRegistry; - - protected int connectionCount = 0; - - protected ByteBufferPool byteBufferPool; - - protected CharsetDecoder decoder = CHARSET.newDecoder(); - - protected CharsetEncoder encoder = CHARSET.newEncoder(); - - /** - * Creates a Services Server Base. Sets internal variables, but does not bind the port. Port - * binding is to be handled by sublcasses. - * - * @param portNumber - * the port number to use for communicating. - * @param translationScope - * the TranslationSpace to use for incoming messages; if this is null, uses - * DefaultServicesTranslations instead. - * @param objectRegistry - * Provides a context for request processing; if this is null, creates a new - * ObjectRegistry. - * @throws IOException - * if an I/O error occurs while trying to open a Selector from the system. - */ - protected NIONetworking(String networkIdentifier, int portNumber, - SimplTypesScope translationScope, S objectRegistry, int maxMessageSizeChars) - throws IOException - { - super(networkIdentifier, portNumber); - - if (translationScope == null) - translationScope = DefaultServicesTranslations.get(); - - this.translationScope = translationScope; - - this.objectRegistry = objectRegistry; - - readBuffer = ByteBuffer.allocateDirect((int) Math.ceil(maxMessageSizeChars - * encoder.maxBytesPerChar())); - this.byteBufferPool = new ByteBufferPool(10, 10, (int) Math.ceil(maxMessageSizeChars - * encoder.maxBytesPerChar())); - } - - /** - * @see ecologylab.oodss.distributed.impl.NIOCore#readReady(java.nio.channels.SelectionKey) - */ - @Override - protected void readReady(SelectionKey key) throws ClientOfflineException, BadClientException - { - readKey(key); - } - - /** - * @see ecologylab.oodss.distributed.impl.NIOCore#writeReady(java.nio.channels.SelectionKey) - */ - @Override - protected void writeReady(SelectionKey key) throws IOException - { - writeKey(key); - } - - /** - * Queue up bytes to send on a particular socket. This method is typically called by some outside - * context manager, that has produced an encoded message to send out. - * - * @param socketKey - * @param data - */ - public void enqueueBytesForWriting(SelectionKey socketKey, ByteBuffer data) - { - // queue data to write - synchronized (this.pendingWrites) - { - Queue dataQueue = pendingWrites.get(socketKey); - - if (dataQueue == null) - { - dataQueue = new LinkedList(); - pendingWrites.put(socketKey, dataQueue); - } - - dataQueue.offer(data); - } - - this.queueForWrite(socketKey); - - selector.wakeup(); - } - - /** - * Reads all the data from the key into the readBuffer, then pushes that information to the action - * processor for processing. - * - * @param key - * @throws BadClientException - */ - private final void readKey(SelectionKey key) throws BadClientException, ClientOfflineException - { - SocketChannel sc = (SocketChannel) key.channel(); - int bytesRead; - - this.readBuffer.clear(); - - // read - try - { - bytesRead = sc.read(readBuffer); - } - catch (BufferOverflowException e) - { - throw new BadClientException(sc.socket().getInetAddress().getHostAddress(), - "Client overflowed the buffer."); - } - catch (IOException e) - { // error trying to read; client disconnected - throw new ClientOfflineException("Client forcibly closed connection."); - } - - if (bytesRead == -1) - { // connection closed cleanly - throw new ClientOfflineException("Client closed connection cleanly."); - } - else if (bytesRead > 0) - { - readBuffer.flip(); - - // get the session key that was formed at accept(), and send it over as - // the sessionId - this.processReadData(key.attachment(), key, readBuffer, bytesRead); - } - } - - /** - * Writes the bytes from pendingWrites that belong to key. - * - * @param key - * @throws IOException - */ - protected void writeKey(SelectionKey key) throws IOException - { - SocketChannel sc = (SocketChannel) key.channel(); - - synchronized (this.pendingWrites) - { - Queue writes = pendingWrites.get(key); - - while (!writes.isEmpty()) - { // write everything - ByteBuffer bytes = writes.poll(); - - bytes.flip(); - - - while (bytes.remaining() > 0) - { // the socket's buffer filled up!; should go out again next time - //debug("unable to write all data to client; will try again shortly."); - sc.write(bytes); - } - - bytes = this.byteBufferPool.release(bytes); - } - } - } - - /** - * Optional operation. - * - * Called when a key has been marked for accepting. This method should be implemented by servers, - * but clients should leave this blank, unless they are also acting as servers (accepting incoming - * connections). - * - * @param key - * @throws OperationNotSupportedException - */ - protected abstract void acceptKey(SelectionKey key); - - /** - * Remove the argument passed in from the set of connections we know about. - */ - protected void connectionTerminated() - { - connectionCount--; - // When thread close by unexpected way (such as client just crashes), - // this method will end the service gracefully. - terminationAction(); - } - - /** - * This method is called whenever bytes have been read from a socket. There is no guaranty that - * the bytes will be a valid or complete message, nor is there a guaranty about what said bytes - * encode. Implementations should be prepared to handle incomplete messages, multiple messages, or - * malformed messages in this method. - * - * @param sessionToken - * the id being use for this session. - * @param sc - * the SocketChannel from which the bytes originated. - * @param bytes - * the bytes read from the SocketChannel. - * @param bytesRead - * the number of bytes in the bytes array. - * @throws BadClientException - * if the client from which the bytes were read has transmitted something inappropriate, - * such as data too large for a buffer or a possibly malicious message. - */ - protected abstract void processReadData(Object sessionToken, SelectionKey sk, ByteBuffer bytes, - int bytesRead) throws BadClientException; - - /** - * This defines the actions that server needs to perform when the client ends unexpected way. - * Detail implementations will be in subclasses. - */ - protected void terminationAction() - { - - } - - /** - * Retrieves a ByteBuffer object from this's pool of ByteBuffers. Typically used by a - * ContextManager to store bytes that will be later enqueued to write (and thus released by that - * method). - * - * @return - */ - public ByteBuffer acquireByteBufferFromPool() - { - return this.byteBufferPool.acquire(); - } -} +/* + * Created on Mar 2, 2007 + */ +package ecologylab.oodss.distributed.impl; + +import java.io.IOException; +import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.SocketChannel; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; + +import javax.naming.OperationNotSupportedException; + +import ecologylab.collections.Scope; +import ecologylab.io.ByteBufferPool; +import ecologylab.oodss.exceptions.BadClientException; +import ecologylab.oodss.exceptions.ClientOfflineException; +import ecologylab.oodss.messages.DefaultServicesTranslations; +import ecologylab.serialization.SimplTypesScope; + +/** + * Handles backend, low-level communication between distributed programs, using NIO. This is the + * basis for servers for handling network communication. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public abstract class NIONetworking extends NIOCore +{ + /** + * ByteBuffer that holds all incoming communication temporarily, immediately after it is read. + */ + private final ByteBuffer readBuffer; + + /** + * Maps SocketChannels (connections) to their write Queues of ByteBuffers. Whenever a + * SocketChannel is marked for writing, and comes up for writing, the server will write the set of + * ByteBuffers to the socket. + */ + private Map> pendingWrites = new HashMap>(); + + protected boolean shuttingDown = false; + + /** + * Space that defines mappings between xml names, and Java class names, for request messages. + */ + protected SimplTypesScope translationScope; + + /** Provides a context for request processing. */ + protected S objectRegistry; + + protected int connectionCount = 0; + + protected ByteBufferPool byteBufferPool; + + protected CharsetDecoder decoder = CHARSET.newDecoder(); + + protected CharsetEncoder encoder = CHARSET.newEncoder(); + + /** + * Creates a Services Server Base. Sets internal variables, but does not bind the port. Port + * binding is to be handled by sublcasses. + * + * @param portNumber + * the port number to use for communicating. + * @param translationScope + * the TranslationSpace to use for incoming messages; if this is null, uses + * DefaultServicesTranslations instead. + * @param objectRegistry + * Provides a context for request processing; if this is null, creates a new + * ObjectRegistry. + * @throws IOException + * if an I/O error occurs while trying to open a Selector from the system. + */ + protected NIONetworking(String networkIdentifier, int portNumber, + SimplTypesScope translationScope, S objectRegistry, int maxMessageSizeChars) + throws IOException + { + super(networkIdentifier, portNumber); + + if (translationScope == null) + translationScope = DefaultServicesTranslations.get(); + + this.translationScope = translationScope; + + this.objectRegistry = objectRegistry; + + readBuffer = ByteBuffer.allocateDirect((int) Math.ceil(maxMessageSizeChars + * encoder.maxBytesPerChar())); + this.byteBufferPool = new ByteBufferPool(10, 10, (int) Math.ceil(maxMessageSizeChars + * encoder.maxBytesPerChar())); + } + + /** + * @see ecologylab.oodss.distributed.impl.NIOCore#readReady(java.nio.channels.SelectionKey) + */ + @Override + protected void readReady(SelectionKey key) throws ClientOfflineException, BadClientException + { + readKey(key); + } + + /** + * @see ecologylab.oodss.distributed.impl.NIOCore#writeReady(java.nio.channels.SelectionKey) + */ + @Override + protected void writeReady(SelectionKey key) throws IOException + { + writeKey(key); + } + + /** + * Queue up bytes to send on a particular socket. This method is typically called by some outside + * context manager, that has produced an encoded message to send out. + * + * @param socketKey + * @param data + */ + public void enqueueBytesForWriting(SelectionKey socketKey, ByteBuffer data) + { + // queue data to write + synchronized (this.pendingWrites) + { + Queue dataQueue = pendingWrites.get(socketKey); + + if (dataQueue == null) + { + dataQueue = new LinkedList(); + pendingWrites.put(socketKey, dataQueue); + } + + dataQueue.offer(data); + } + + this.queueForWrite(socketKey); + + selector.wakeup(); + } + + /** + * Reads all the data from the key into the readBuffer, then pushes that information to the action + * processor for processing. + * + * @param key + * @throws BadClientException + */ + private final void readKey(SelectionKey key) throws BadClientException, ClientOfflineException + { + SocketChannel sc = (SocketChannel) key.channel(); + int bytesRead; + + this.readBuffer.clear(); + + // read + try + { + bytesRead = sc.read(readBuffer); + } + catch (BufferOverflowException e) + { + throw new BadClientException(sc.socket().getInetAddress().getHostAddress(), + "Client overflowed the buffer."); + } + catch (IOException e) + { // error trying to read; client disconnected + throw new ClientOfflineException("Client forcibly closed connection."); + } + + if (bytesRead == -1) + { // connection closed cleanly + throw new ClientOfflineException("Client closed connection cleanly."); + } + else if (bytesRead > 0) + { + readBuffer.flip(); + + // get the session key that was formed at accept(), and send it over as + // the sessionId + this.processReadData(key.attachment(), key, readBuffer, bytesRead); + } + } + + /** + * Writes the bytes from pendingWrites that belong to key. + * + * @param key + * @throws IOException + */ + protected void writeKey(SelectionKey key) throws IOException + { + SocketChannel sc = (SocketChannel) key.channel(); + + synchronized (this.pendingWrites) + { + Queue writes = pendingWrites.get(key); + + while (!writes.isEmpty()) + { // write everything + ByteBuffer bytes = writes.poll(); + + bytes.flip(); + + + while (bytes.remaining() > 0) + { // the socket's buffer filled up!; should go out again next time + //debug("unable to write all data to client; will try again shortly."); + sc.write(bytes); + } + + bytes = this.byteBufferPool.release(bytes); + } + } + } + + /** + * Optional operation. + * + * Called when a key has been marked for accepting. This method should be implemented by servers, + * but clients should leave this blank, unless they are also acting as servers (accepting incoming + * connections). + * + * @param key + * @throws OperationNotSupportedException + */ + protected abstract void acceptKey(SelectionKey key); + + /** + * Remove the argument passed in from the set of connections we know about. + */ + protected void connectionTerminated() + { + connectionCount--; + // When thread close by unexpected way (such as client just crashes), + // this method will end the service gracefully. + terminationAction(); + } + + /** + * This method is called whenever bytes have been read from a socket. There is no guaranty that + * the bytes will be a valid or complete message, nor is there a guaranty about what said bytes + * encode. Implementations should be prepared to handle incomplete messages, multiple messages, or + * malformed messages in this method. + * + * @param sessionToken + * the id being use for this session. + * @param sc + * the SocketChannel from which the bytes originated. + * @param bytes + * the bytes read from the SocketChannel. + * @param bytesRead + * the number of bytes in the bytes array. + * @throws BadClientException + * if the client from which the bytes were read has transmitted something inappropriate, + * such as data too large for a buffer or a possibly malicious message. + */ + protected abstract void processReadData(Object sessionToken, SelectionKey sk, ByteBuffer bytes, + int bytesRead) throws BadClientException; + + /** + * This defines the actions that server needs to perform when the client ends unexpected way. + * Detail implementations will be in subclasses. + */ + protected void terminationAction() + { + + } + + /** + * Retrieves a ByteBuffer object from this's pool of ByteBuffers. Typically used by a + * ContextManager to store bytes that will be later enqueued to write (and thus released by that + * method). + * + * @return + */ + public ByteBuffer acquireByteBufferFromPool() + { + return this.byteBufferPool.acquire(); + } +} diff --git a/simplCore/src/ecologylab/oodss/distributed/impl/NIOServerIOThread.java b/simplCore/src/ecologylab/oodss/distributed/impl/NIOServerIOThread.java index bffe3d18..843653fb 100644 --- a/simplCore/src/ecologylab/oodss/distributed/impl/NIOServerIOThread.java +++ b/simplCore/src/ecologylab/oodss/distributed/impl/NIOServerIOThread.java @@ -1,518 +1,518 @@ -/* - * Created on May 3, 2006 - */ -package ecologylab.oodss.distributed.impl; - -import java.io.IOException; -import java.net.BindException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.nio.channels.SelectionKey; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Map; - -import javax.xml.bind.DatatypeConverter; - -import ecologylab.collections.Scope; -import ecologylab.generic.ObjectOrHashMap; -import ecologylab.oodss.distributed.common.ServerConstants; -import ecologylab.oodss.distributed.server.NIOServerDataReader; -import ecologylab.oodss.exceptions.BadClientException; -import ecologylab.serialization.SimplTypesScope; - -/** - * The backend portion of the NIO Server, which handles low-level communication with clients. - * - * Re-written based on the Rox Java NIO Tutorial - * (http://rox-xmlrpc.sourceforge.net/niotut/index.html). - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class NIOServerIOThread extends NIONetworking implements ServerConstants -{ - static NIOServerIOThread getInstance(int portNumber, InetAddress[] hostAddresses, - NIOServerDataReader sAP, SimplTypesScope requestTranslationSpace, Scope objectRegistry, - int idleSocketTimeout, int maxMessageLength) throws IOException, BindException - { - return new NIOServerIOThread(portNumber, hostAddresses, sAP, requestTranslationSpace, - objectRegistry, idleSocketTimeout, maxMessageLength); - } - - private final ArrayList incomingConnectionSockets = new ArrayList(); - - private NIOServerDataReader sAP; - - private int idleSocketTimeout; - - private Map keyActivityTimes = new HashMap(); - - private Map> ipToKeyOrKeys = new HashMap>(); - - private boolean acceptEnabled = false; - - private MessageDigest digester; - - private long dispensedTokens; - - private InetAddress[] hostAddresses; - - private final ArrayList boundAddresses = new ArrayList(); - - protected NIOServerIOThread(int portNumber, InetAddress[] hostAddresses, NIOServerDataReader sAP, - SimplTypesScope requestTranslationSpace, Scope objectRegistry, int idleSocketTimeout, - int maxMessageLength) throws IOException, BindException - { - super("NIOServer", portNumber, requestTranslationSpace, objectRegistry, maxMessageLength); - - this.construct(hostAddresses, sAP, idleSocketTimeout); - } - - private void construct(InetAddress[] newHostAddresses, NIOServerDataReader newFrontend, - int newIdleSocketTimeout) throws IOException - { - this.hostAddresses = newHostAddresses; - - this.sAP = newFrontend; - - this.idleSocketTimeout = newIdleSocketTimeout; - - try - { - digester = MessageDigest.getInstance("SHA-256"); - } - catch (NoSuchAlgorithmException e) - { - weird("This can only happen if the local implementation does not include the given hash algorithm."); - e.printStackTrace(); - } - } - - /** - * Gets all host addresses associated with this server. - * - * @return - */ - public InetAddress[] getHostAddresses() - { - return hostAddresses; - } - - /** - * Checks all of the current keys to see if they have been idle for too long and drops them if - * they have. - * - */ - @Override - protected void checkAndDropIdleKeys() - { - LinkedList keysToInvalidate = new LinkedList(); - long timeStamp = System.currentTimeMillis(); - - if (idleSocketTimeout > -1) - { /* - * after we select, we'll check to see if we need to boot any idle keys - */ - for (SelectionKey sKey : keyActivityTimes.keySet()) - { - if ((timeStamp - keyActivityTimes.get(sKey)) > idleSocketTimeout) - { - keysToInvalidate.add(sKey); - } - } - } - else - { /* - * We have to clean up the key set at some point; use GARBAGE_CONNECTION_CLEANUP_TIMEOUT - */ - for (SelectionKey sKey : keyActivityTimes.keySet()) - { - if ((timeStamp - keyActivityTimes.get(sKey)) > GARBAGE_CONNECTION_CLEANUP_TIMEOUT) - { - keysToInvalidate.add(sKey); - } - } - } - - // remove all the invalid keys - for (SelectionKey keyToInvalidate : keysToInvalidate) - { - debug(keyToInvalidate.attachment() + " took too long to request; disconnecting."); - keyActivityTimes.remove(keyToInvalidate); - this.setPendingInvalidate(keyToInvalidate, true); - } - } - - /** - * Accept an incoming connection from a client to a server, if the server has connections - * available and the client is not bad. Generate a session identifier and attach it to the - * newly-connected client's SelectionKey, so that a client session manager can be associated with - * the connection. - */ - @Override - protected final void acceptKey(SelectionKey key) - { - try - { - int numConn = selector.keys().size() - 1; - - debug("connections running: " + numConn); - - if (numConn < MAX_CONNECTIONS) - { // the keyset includes this side of the connection - if (numConn - 1 == MAX_CONNECTIONS) - { - debug("Maximum connections reached; disabling accept until a client drops."); - - for (ServerSocket s : this.incomingConnectionSockets) - { - SelectionKey closingKey = s.getChannel().keyFor(this.selector); - closingKey.cancel(); - s.close(); - closingKey.channel().close(); - } - - acceptEnabled = false; - } - - SocketChannel newlyAcceptedChannel = ((ServerSocketChannel) key.channel()).accept(); - - InetAddress address = newlyAcceptedChannel.socket().getInetAddress(); - - debug("new address: " + address.getHostAddress()); - - if (!BadClientException.isEvilHostByNumber(address.getHostAddress())) - { - newlyAcceptedChannel.configureBlocking(false); - - // when we register, we want to attach the proper - // session token to all of the keys associated with - // this connection, so we can sort them out later. - String keyAttachment = this.generateSessionToken(newlyAcceptedChannel.socket()); - - SelectionKey newKey = newlyAcceptedChannel.register(selector, SelectionKey.OP_READ, - keyAttachment); - - this.keyActivityTimes.put(newKey, System.currentTimeMillis()); - - if ((ipToKeyOrKeys.get(address.getHostAddress())) == null) - { - debug(address + " not in our list, adding it."); - - ipToKeyOrKeys.put(address.getHostAddress(), new ObjectOrHashMap( - keyAttachment, newKey)); - } - else - { - debug(address + " is in our list, adding another key."); - synchronized (ipToKeyOrKeys) - { - ipToKeyOrKeys.get(address.getHostAddress()).put(keyAttachment, newKey); - System.out.println("new size: " + ipToKeyOrKeys.get(address.getHostAddress()).size()); - } - } - - debug("Now connected to " - + newlyAcceptedChannel - + ", " - + (MAX_CONNECTIONS - numConn - 1) - + " connections remaining."); - - return; - } - } - - // we will prematurely exit before now if it's a good connection - // so now it's a bad one; disconnect it and return null - SocketChannel tempChannel = ((ServerSocketChannel) key.channel()).accept(); - - InetAddress address = null; - - if (tempChannel != null && tempChannel.socket() != null) - { - address = tempChannel.socket().getInetAddress(); - - // shut it all down - tempChannel.socket().shutdownInput(); - tempChannel.socket().shutdownOutput(); - tempChannel.socket().close(); - tempChannel.close(); - } - // show a debug message - if (numConn >= MAX_CONNECTIONS) - debug("Rejected connection; already fulfilled max connections."); - else - debug("Evil host attempted to connect: " + address); - - } - catch (IOException e) - { - e.printStackTrace(); - } - catch (NullPointerException e) - { - e.printStackTrace(); - } - } - - /** - * @see ecologylab.oodss.distributed.impl.NIONetworking#removeBadConnections() - */ - @Override - protected void removeBadConnections(SelectionKey key) - { - // shut them ALL down! - InetAddress address = ((SocketChannel) key.channel()).socket().getInetAddress(); - - ObjectOrHashMap keyOrKeys = ipToKeyOrKeys.get(address.getHostAddress()); - - Iterator allKeysForIp = keyOrKeys.values().iterator(); - - debug("***********Shutting down all clients from " + address.getHostAddress()); - - while (allKeysForIp.hasNext()) - { - SelectionKey keyForIp = allKeysForIp.next(); - - debug("shutting down " + ((SocketChannel) keyForIp.channel()).socket().getInetAddress()); - - this.setPendingInvalidate(keyForIp, true); - } - - keyOrKeys.clear(); - ipToKeyOrKeys.remove(address.getHostAddress()); - } - - /** - * Handles the client manager for the socket (remove if permanent) and shuts down communication on - * the socket. - * - * @see ecologylab.oodss.distributed.impl.NIONetworking#invalidateKey(java.nio.channels.SocketChannel, - * boolean) - */ - @Override - protected void invalidateKey(SelectionKey key, boolean permanent) - { - SocketChannel chan = (SocketChannel) key.channel(); - InetAddress address = chan.socket().getInetAddress(); - - sAP.invalidate((String) key.attachment(), permanent); - - super.invalidateKey(chan); - - ObjectOrHashMap keyOrKeys = this.ipToKeyOrKeys.get(address - .getHostAddress()); - - if (keyOrKeys != null) - { - keyOrKeys.remove(address); - - if (keyOrKeys.isEmpty()) - { - this.ipToKeyOrKeys.remove(chan.socket().getInetAddress().getHostAddress()); - } - } - this.keyActivityTimes.remove(key); - - /* - * decrement numConnections & if the server disabled new connections due to hitting - * max_connections, re-enable - */ - if (selector.keys().size() < MAX_CONNECTIONS && !acceptEnabled) - { - try - { - this.registerAcceptWithSelector(); - } - catch (IOException e) - { - debug("Unable to re-open socket for accepts; critical failure."); - e.printStackTrace(); - } - } - } - - /** - * Attempts to bind all of the ports in the hostAddresses array. If a port cannot be bound, it is - * removed from the hostAddresses array. - * - * @throws IOException - */ - void registerAcceptWithSelector() throws IOException - { - boundAddresses.clear(); - incomingConnectionSockets.clear(); - - for (int i = 0; i < hostAddresses.length; i++) - { - debug("setting up accept on " + hostAddresses[i] + ": " + portNumber); - - // acquire the static ServerSocketChannel object - ServerSocketChannel channel = ServerSocketChannel.open(); - - // disable blocking - channel.configureBlocking(false); - - try - { - ServerSocket newSocket = channel.socket(); - // get the socket associated with the channel - - // bind to the port for this server - newSocket.bind(new InetSocketAddress(hostAddresses[i], portNumber)); - - newSocket.setReuseAddress(true); - - channel.register(this.selector, SelectionKey.OP_ACCEPT); - - this.incomingConnectionSockets.add(newSocket); - this.boundAddresses.add(hostAddresses[i]); - } - catch (BindException e) - { - debug("Unable to bind " + hostAddresses[i]); - debug(e.getMessage()); - e.printStackTrace(); - } - catch (SocketException e) - { - System.err.println(e.getMessage()); - } - } - - if (this.boundAddresses.size() == 0) - { - throw new BindException("Server was unable to bind to any addresses."); - } - - // register the channel with the selector to look for incoming - // accept requests - acceptEnabled = true; - } - - /** - * Generates a unique identifier String for the given socket, based upon actual ports used and ip - * addresses with a hash. Called by the server at accept() time, and used to identify the - * connection thereafter. - * - * @param incomingSocket - * @return - */ - protected String generateSessionToken(Socket incomingSocket) - { - // clear digester - digester.reset(); - - // we make a string consisting of the following: - // time of initial connection (when this method is called), - // client ip, client actual port - digester.update(String.valueOf(System.currentTimeMillis()).getBytes()); - // digester.update(String.valueOf(System.nanoTime()).getBytes()); - // digester.update(this.incomingConnectionSockets[0].getInetAddress() - // .toString().getBytes()); - digester.update(incomingSocket.getInetAddress().toString().getBytes()); - digester.update(String.valueOf(incomingSocket.getPort()).getBytes()); - - digester.update(String.valueOf(this.dispensedTokens).getBytes()); - - dispensedTokens++; - - // convert to normal characters and return as a String - return DatatypeConverter.printBase64Binary(digester.digest()); - } - - @Override - protected void close() - { - try - { - debug("Closing selector."); - selector.close(); - - debug("Unbinding."); - for (ServerSocket s : incomingConnectionSockets) - { - s.close(); - } - } - catch (IOException e) - { - e.printStackTrace(); - } - } - - @Override - protected void processReadData(Object sessionToken, SelectionKey sk, ByteBuffer bytes, - int bytesRead) throws BadClientException - { - this.sAP.processRead(sessionToken, this, sk, bytes, bytesRead); - this.keyActivityTimes.put(sk, System.currentTimeMillis()); - } - - /** - * @see ecologylab.oodss.distributed.impl.NIOCore#acceptReady(java.nio.channels.SelectionKey) - */ - @Override - protected void acceptReady(SelectionKey key) - { - this.acceptKey(key); - } - - /** - * @see ecologylab.oodss.distributed.impl.NIOCore#connectReady(java.nio.channels.SelectionKey) - */ - @Override - protected void connectReady(SelectionKey key) - { - } - - /** - * @see ecologylab.oodss.distributed.impl.NIOCore#readFinished(java.nio.channels.SelectionKey) - */ - @Override - protected void readFinished(SelectionKey key) - { - } - - /** - * @param socket - * @param permanent - */ - public void setPendingInvalidate(SocketChannel socket, boolean permanent) - { - this.setPendingInvalidate(socket.keyFor(selector), permanent); - } - - /** - * @see ecologylab.oodss.distributed.impl.NIOCore#acceptFinished(java.nio.channels.SelectionKey) - */ - @Override - public void acceptFinished(SelectionKey key) - { - } - - @Override - protected boolean handleInvalidate(SelectionKey key, boolean forcePermanent) - { - return this.sAP.invalidate((String) key.attachment(), forcePermanent); - } - - /** - * @return the boundAddresses - */ - public ArrayList getBoundAddresses() - { - return boundAddresses; - } -} +/* + * Created on May 3, 2006 + */ +package ecologylab.oodss.distributed.impl; + +import java.io.IOException; +import java.net.BindException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; + +import javax.xml.bind.DatatypeConverter; + +import ecologylab.collections.Scope; +import ecologylab.generic.ObjectOrHashMap; +import ecologylab.oodss.distributed.common.ServerConstants; +import ecologylab.oodss.distributed.server.NIOServerDataReader; +import ecologylab.oodss.exceptions.BadClientException; +import ecologylab.serialization.SimplTypesScope; + +/** + * The backend portion of the NIO Server, which handles low-level communication with clients. + * + * Re-written based on the Rox Java NIO Tutorial + * (http://rox-xmlrpc.sourceforge.net/niotut/index.html). + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class NIOServerIOThread extends NIONetworking implements ServerConstants +{ + static NIOServerIOThread getInstance(int portNumber, InetAddress[] hostAddresses, + NIOServerDataReader sAP, SimplTypesScope requestTranslationSpace, Scope objectRegistry, + int idleSocketTimeout, int maxMessageLength) throws IOException, BindException + { + return new NIOServerIOThread(portNumber, hostAddresses, sAP, requestTranslationSpace, + objectRegistry, idleSocketTimeout, maxMessageLength); + } + + private final ArrayList incomingConnectionSockets = new ArrayList(); + + private NIOServerDataReader sAP; + + private int idleSocketTimeout; + + private Map keyActivityTimes = new HashMap(); + + private Map> ipToKeyOrKeys = new HashMap>(); + + private boolean acceptEnabled = false; + + private MessageDigest digester; + + private long dispensedTokens; + + private InetAddress[] hostAddresses; + + private final ArrayList boundAddresses = new ArrayList(); + + protected NIOServerIOThread(int portNumber, InetAddress[] hostAddresses, NIOServerDataReader sAP, + SimplTypesScope requestTranslationSpace, Scope objectRegistry, int idleSocketTimeout, + int maxMessageLength) throws IOException, BindException + { + super("NIOServer", portNumber, requestTranslationSpace, objectRegistry, maxMessageLength); + + this.construct(hostAddresses, sAP, idleSocketTimeout); + } + + private void construct(InetAddress[] newHostAddresses, NIOServerDataReader newFrontend, + int newIdleSocketTimeout) throws IOException + { + this.hostAddresses = newHostAddresses; + + this.sAP = newFrontend; + + this.idleSocketTimeout = newIdleSocketTimeout; + + try + { + digester = MessageDigest.getInstance("SHA-256"); + } + catch (NoSuchAlgorithmException e) + { + weird("This can only happen if the local implementation does not include the given hash algorithm."); + e.printStackTrace(); + } + } + + /** + * Gets all host addresses associated with this server. + * + * @return + */ + public InetAddress[] getHostAddresses() + { + return hostAddresses; + } + + /** + * Checks all of the current keys to see if they have been idle for too long and drops them if + * they have. + * + */ + @Override + protected void checkAndDropIdleKeys() + { + LinkedList keysToInvalidate = new LinkedList(); + long timeStamp = System.currentTimeMillis(); + + if (idleSocketTimeout > -1) + { /* + * after we select, we'll check to see if we need to boot any idle keys + */ + for (SelectionKey sKey : keyActivityTimes.keySet()) + { + if ((timeStamp - keyActivityTimes.get(sKey)) > idleSocketTimeout) + { + keysToInvalidate.add(sKey); + } + } + } + else + { /* + * We have to clean up the key set at some point; use GARBAGE_CONNECTION_CLEANUP_TIMEOUT + */ + for (SelectionKey sKey : keyActivityTimes.keySet()) + { + if ((timeStamp - keyActivityTimes.get(sKey)) > GARBAGE_CONNECTION_CLEANUP_TIMEOUT) + { + keysToInvalidate.add(sKey); + } + } + } + + // remove all the invalid keys + for (SelectionKey keyToInvalidate : keysToInvalidate) + { + debug(keyToInvalidate.attachment() + " took too long to request; disconnecting."); + keyActivityTimes.remove(keyToInvalidate); + this.setPendingInvalidate(keyToInvalidate, true); + } + } + + /** + * Accept an incoming connection from a client to a server, if the server has connections + * available and the client is not bad. Generate a session identifier and attach it to the + * newly-connected client's SelectionKey, so that a client session manager can be associated with + * the connection. + */ + @Override + protected final void acceptKey(SelectionKey key) + { + try + { + int numConn = selector.keys().size() - 1; + + debug("connections running: " + numConn); + + if (numConn < MAX_CONNECTIONS) + { // the keyset includes this side of the connection + if (numConn - 1 == MAX_CONNECTIONS) + { + debug("Maximum connections reached; disabling accept until a client drops."); + + for (ServerSocket s : this.incomingConnectionSockets) + { + SelectionKey closingKey = s.getChannel().keyFor(this.selector); + closingKey.cancel(); + s.close(); + closingKey.channel().close(); + } + + acceptEnabled = false; + } + + SocketChannel newlyAcceptedChannel = ((ServerSocketChannel) key.channel()).accept(); + + InetAddress address = newlyAcceptedChannel.socket().getInetAddress(); + + debug("new address: " + address.getHostAddress()); + + if (!BadClientException.isEvilHostByNumber(address.getHostAddress())) + { + newlyAcceptedChannel.configureBlocking(false); + + // when we register, we want to attach the proper + // session token to all of the keys associated with + // this connection, so we can sort them out later. + String keyAttachment = this.generateSessionToken(newlyAcceptedChannel.socket()); + + SelectionKey newKey = newlyAcceptedChannel.register(selector, SelectionKey.OP_READ, + keyAttachment); + + this.keyActivityTimes.put(newKey, System.currentTimeMillis()); + + if ((ipToKeyOrKeys.get(address.getHostAddress())) == null) + { + debug(address + " not in our list, adding it."); + + ipToKeyOrKeys.put(address.getHostAddress(), new ObjectOrHashMap( + keyAttachment, newKey)); + } + else + { + debug(address + " is in our list, adding another key."); + synchronized (ipToKeyOrKeys) + { + ipToKeyOrKeys.get(address.getHostAddress()).put(keyAttachment, newKey); + System.out.println("new size: " + ipToKeyOrKeys.get(address.getHostAddress()).size()); + } + } + + debug("Now connected to " + + newlyAcceptedChannel + + ", " + + (MAX_CONNECTIONS - numConn - 1) + + " connections remaining."); + + return; + } + } + + // we will prematurely exit before now if it's a good connection + // so now it's a bad one; disconnect it and return null + SocketChannel tempChannel = ((ServerSocketChannel) key.channel()).accept(); + + InetAddress address = null; + + if (tempChannel != null && tempChannel.socket() != null) + { + address = tempChannel.socket().getInetAddress(); + + // shut it all down + tempChannel.socket().shutdownInput(); + tempChannel.socket().shutdownOutput(); + tempChannel.socket().close(); + tempChannel.close(); + } + // show a debug message + if (numConn >= MAX_CONNECTIONS) + debug("Rejected connection; already fulfilled max connections."); + else + debug("Evil host attempted to connect: " + address); + + } + catch (IOException e) + { + e.printStackTrace(); + } + catch (NullPointerException e) + { + e.printStackTrace(); + } + } + + /** + * @see ecologylab.oodss.distributed.impl.NIONetworking#removeBadConnections() + */ + @Override + protected void removeBadConnections(SelectionKey key) + { + // shut them ALL down! + InetAddress address = ((SocketChannel) key.channel()).socket().getInetAddress(); + + ObjectOrHashMap keyOrKeys = ipToKeyOrKeys.get(address.getHostAddress()); + + Iterator allKeysForIp = keyOrKeys.values().iterator(); + + debug("***********Shutting down all clients from " + address.getHostAddress()); + + while (allKeysForIp.hasNext()) + { + SelectionKey keyForIp = allKeysForIp.next(); + + debug("shutting down " + ((SocketChannel) keyForIp.channel()).socket().getInetAddress()); + + this.setPendingInvalidate(keyForIp, true); + } + + keyOrKeys.clear(); + ipToKeyOrKeys.remove(address.getHostAddress()); + } + + /** + * Handles the client manager for the socket (remove if permanent) and shuts down communication on + * the socket. + * + * @see ecologylab.oodss.distributed.impl.NIONetworking#invalidateKey(java.nio.channels.SocketChannel, + * boolean) + */ + @Override + protected void invalidateKey(SelectionKey key, boolean permanent) + { + SocketChannel chan = (SocketChannel) key.channel(); + InetAddress address = chan.socket().getInetAddress(); + + sAP.invalidate((String) key.attachment(), permanent); + + super.invalidateKey(chan); + + ObjectOrHashMap keyOrKeys = this.ipToKeyOrKeys.get(address + .getHostAddress()); + + if (keyOrKeys != null) + { + keyOrKeys.remove(address); + + if (keyOrKeys.isEmpty()) + { + this.ipToKeyOrKeys.remove(chan.socket().getInetAddress().getHostAddress()); + } + } + this.keyActivityTimes.remove(key); + + /* + * decrement numConnections & if the server disabled new connections due to hitting + * max_connections, re-enable + */ + if (selector.keys().size() < MAX_CONNECTIONS && !acceptEnabled) + { + try + { + this.registerAcceptWithSelector(); + } + catch (IOException e) + { + debug("Unable to re-open socket for accepts; critical failure."); + e.printStackTrace(); + } + } + } + + /** + * Attempts to bind all of the ports in the hostAddresses array. If a port cannot be bound, it is + * removed from the hostAddresses array. + * + * @throws IOException + */ + void registerAcceptWithSelector() throws IOException + { + boundAddresses.clear(); + incomingConnectionSockets.clear(); + + for (int i = 0; i < hostAddresses.length; i++) + { + debug("setting up accept on " + hostAddresses[i] + ": " + portNumber); + + // acquire the static ServerSocketChannel object + ServerSocketChannel channel = ServerSocketChannel.open(); + + // disable blocking + channel.configureBlocking(false); + + try + { + ServerSocket newSocket = channel.socket(); + // get the socket associated with the channel + + // bind to the port for this server + newSocket.bind(new InetSocketAddress(hostAddresses[i], portNumber)); + + newSocket.setReuseAddress(true); + + channel.register(this.selector, SelectionKey.OP_ACCEPT); + + this.incomingConnectionSockets.add(newSocket); + this.boundAddresses.add(hostAddresses[i]); + } + catch (BindException e) + { + debug("Unable to bind " + hostAddresses[i]); + debug(e.getMessage()); + e.printStackTrace(); + } + catch (SocketException e) + { + System.err.println(e.getMessage()); + } + } + + if (this.boundAddresses.size() == 0) + { + throw new BindException("Server was unable to bind to any addresses."); + } + + // register the channel with the selector to look for incoming + // accept requests + acceptEnabled = true; + } + + /** + * Generates a unique identifier String for the given socket, based upon actual ports used and ip + * addresses with a hash. Called by the server at accept() time, and used to identify the + * connection thereafter. + * + * @param incomingSocket + * @return + */ + protected String generateSessionToken(Socket incomingSocket) + { + // clear digester + digester.reset(); + + // we make a string consisting of the following: + // time of initial connection (when this method is called), + // client ip, client actual port + digester.update(String.valueOf(System.currentTimeMillis()).getBytes()); + // digester.update(String.valueOf(System.nanoTime()).getBytes()); + // digester.update(this.incomingConnectionSockets[0].getInetAddress() + // .toString().getBytes()); + digester.update(incomingSocket.getInetAddress().toString().getBytes()); + digester.update(String.valueOf(incomingSocket.getPort()).getBytes()); + + digester.update(String.valueOf(this.dispensedTokens).getBytes()); + + dispensedTokens++; + + // convert to normal characters and return as a String + return DatatypeConverter.printBase64Binary(digester.digest()); + } + + @Override + protected void close() + { + try + { + debug("Closing selector."); + selector.close(); + + debug("Unbinding."); + for (ServerSocket s : incomingConnectionSockets) + { + s.close(); + } + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + @Override + protected void processReadData(Object sessionToken, SelectionKey sk, ByteBuffer bytes, + int bytesRead) throws BadClientException + { + this.sAP.processRead(sessionToken, this, sk, bytes, bytesRead); + this.keyActivityTimes.put(sk, System.currentTimeMillis()); + } + + /** + * @see ecologylab.oodss.distributed.impl.NIOCore#acceptReady(java.nio.channels.SelectionKey) + */ + @Override + protected void acceptReady(SelectionKey key) + { + this.acceptKey(key); + } + + /** + * @see ecologylab.oodss.distributed.impl.NIOCore#connectReady(java.nio.channels.SelectionKey) + */ + @Override + protected void connectReady(SelectionKey key) + { + } + + /** + * @see ecologylab.oodss.distributed.impl.NIOCore#readFinished(java.nio.channels.SelectionKey) + */ + @Override + protected void readFinished(SelectionKey key) + { + } + + /** + * @param socket + * @param permanent + */ + public void setPendingInvalidate(SocketChannel socket, boolean permanent) + { + this.setPendingInvalidate(socket.keyFor(selector), permanent); + } + + /** + * @see ecologylab.oodss.distributed.impl.NIOCore#acceptFinished(java.nio.channels.SelectionKey) + */ + @Override + public void acceptFinished(SelectionKey key) + { + } + + @Override + protected boolean handleInvalidate(SelectionKey key, boolean forcePermanent) + { + return this.sAP.invalidate((String) key.attachment(), forcePermanent); + } + + /** + * @return the boundAddresses + */ + public ArrayList getBoundAddresses() + { + return boundAddresses; + } +} diff --git a/simplCore/src/ecologylab/oodss/distributed/impl/PreppedRequest.java b/simplCore/src/ecologylab/oodss/distributed/impl/PreppedRequest.java index 4d01dfa7..1b3b3b90 100644 --- a/simplCore/src/ecologylab/oodss/distributed/impl/PreppedRequest.java +++ b/simplCore/src/ecologylab/oodss/distributed/impl/PreppedRequest.java @@ -1,106 +1,106 @@ -/* - * Created on Apr 4, 2007 - */ -package ecologylab.oodss.distributed.impl; - -import ecologylab.generic.Debug; - -/** - * Represents a RequestMessage that has been translated to XML. This object encapsulates the XML - * String, along with the request's UID. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class PreppedRequest extends Debug implements Comparable -{ - private long uid = -1; - - private StringBuilder request; - - private boolean disposable; - - /** - * - */ - public PreppedRequest(StringBuilder request, long uid, int requestSize, boolean disposable) - { - this(requestSize); - - this.uid = uid; - - this.setRequest(request); - - this.disposable = disposable; - } - - public PreppedRequest(int requestSize) - { - this.request = new StringBuilder(requestSize); - } - - /** - * Resets this PreppedRequest for re-use. - */ - public void clear() - { - this.uid = -1; - request.setLength(0); - this.disposable = false; - } - - /** - * @return the request - */ - public StringBuilder getRequest() - { - return request; - } - - public void setRequest(StringBuilder request) - { - this.request.setLength(0); - this.request.append(request); - -// debug(request.toString()); - } - - /** - * @return the uid - */ - public long getUid() - { - return uid; - } - - @Override - public int compareTo(PreppedRequest arg0) - { - return (int) (this.uid - arg0.getUid()); - } - - /** - * @param uid - * the uid to set - */ - public void setUid(long uid) - { - this.uid = uid; - } - - /** - * @return the disposable - */ - public boolean isDisposable() - { - return disposable; - } - - /** - * @param disposable - * the disposable to set - */ - public void setDisposable(boolean disposable) - { - this.disposable = disposable; - } -} +/* + * Created on Apr 4, 2007 + */ +package ecologylab.oodss.distributed.impl; + +import ecologylab.generic.Debug; + +/** + * Represents a RequestMessage that has been translated to XML. This object encapsulates the XML + * String, along with the request's UID. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class PreppedRequest extends Debug implements Comparable +{ + private long uid = -1; + + private StringBuilder request; + + private boolean disposable; + + /** + * + */ + public PreppedRequest(StringBuilder request, long uid, int requestSize, boolean disposable) + { + this(requestSize); + + this.uid = uid; + + this.setRequest(request); + + this.disposable = disposable; + } + + public PreppedRequest(int requestSize) + { + this.request = new StringBuilder(requestSize); + } + + /** + * Resets this PreppedRequest for re-use. + */ + public void clear() + { + this.uid = -1; + request.setLength(0); + this.disposable = false; + } + + /** + * @return the request + */ + public StringBuilder getRequest() + { + return request; + } + + public void setRequest(StringBuilder request) + { + this.request.setLength(0); + this.request.append(request); + +// debug(request.toString()); + } + + /** + * @return the uid + */ + public long getUid() + { + return uid; + } + + @Override + public int compareTo(PreppedRequest arg0) + { + return (int) (this.uid - arg0.getUid()); + } + + /** + * @param uid + * the uid to set + */ + public void setUid(long uid) + { + this.uid = uid; + } + + /** + * @return the disposable + */ + public boolean isDisposable() + { + return disposable; + } + + /** + * @param disposable + * the disposable to set + */ + public void setDisposable(boolean disposable) + { + this.disposable = disposable; + } +} diff --git a/simplCore/src/ecologylab/oodss/distributed/impl/PreppedRequestPool.java b/simplCore/src/ecologylab/oodss/distributed/impl/PreppedRequestPool.java index 8ee03732..d4cd1b14 100644 --- a/simplCore/src/ecologylab/oodss/distributed/impl/PreppedRequestPool.java +++ b/simplCore/src/ecologylab/oodss/distributed/impl/PreppedRequestPool.java @@ -1,41 +1,41 @@ -/** - * - */ -package ecologylab.oodss.distributed.impl; - -import ecologylab.generic.ResourcePoolWithSize; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class PreppedRequestPool extends ResourcePoolWithSize -{ - - /** - * @param initialPoolSize - * @param minimumPoolSize - * @param resourceObjectCapacity - */ - public PreppedRequestPool(int initialPoolSize, int minimumPoolSize, int resourceObjectCapacity) - { - super(initialPoolSize, minimumPoolSize, resourceObjectCapacity); - } - - /** - * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) - */ - @Override protected void clean(PreppedRequest objectToClean) - { - objectToClean.clear(); - } - - /** - * @see ecologylab.generic.ResourcePool#generateNewResource() - */ - @Override protected PreppedRequest generateNewResource() - { - return new PreppedRequest(this.resourceObjectCapacity); - } - -} +/** + * + */ +package ecologylab.oodss.distributed.impl; + +import ecologylab.generic.ResourcePoolWithSize; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class PreppedRequestPool extends ResourcePoolWithSize +{ + + /** + * @param initialPoolSize + * @param minimumPoolSize + * @param resourceObjectCapacity + */ + public PreppedRequestPool(int initialPoolSize, int minimumPoolSize, int resourceObjectCapacity) + { + super(initialPoolSize, minimumPoolSize, resourceObjectCapacity); + } + + /** + * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) + */ + @Override protected void clean(PreppedRequest objectToClean) + { + objectToClean.clear(); + } + + /** + * @see ecologylab.generic.ResourcePool#generateNewResource() + */ + @Override protected PreppedRequest generateNewResource() + { + return new PreppedRequest(this.resourceObjectCapacity); + } + +} diff --git a/simplCore/src/ecologylab/oodss/distributed/impl/Shutdownable.java b/simplCore/src/ecologylab/oodss/distributed/impl/Shutdownable.java index a0b2dbae..6c351757 100644 --- a/simplCore/src/ecologylab/oodss/distributed/impl/Shutdownable.java +++ b/simplCore/src/ecologylab/oodss/distributed/impl/Shutdownable.java @@ -1,44 +1,44 @@ -/** - * - */ -package ecologylab.oodss.distributed.impl; - -import java.awt.event.ActionListener; - -/** - * Interface for objects that should have a shutdown sequence. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public interface Shutdownable -{ - public static final String SHUTTING_DOWN = "SHUTTING_DOWN"; - - /** - * Causes this to start to shutdown, and fires a SHUTTING_DOWN event to all - * listeners. - */ - public void shutdown(); - - /** - * This method allows another application to indicate its dependence on this - * to be shutdown. That is, when this's shutdown() method is called, it - * should call the shutdown() method on each component that depends on it. - * - * Implementors and callers should take care not to create an infinite loop - * of shutdown() calls through this method. - * - * @param s - */ - public void addDependentShutdownable(Shutdownable s); - - /** - * This method allows other components to be notified when the shutdown() - * method is called. Listeners will get an ActionEvent whose action command - * is SHUTTING_DOWN. - * - * @param l - */ - public void addShutdownListener(ActionListener l); -} +/** + * + */ +package ecologylab.oodss.distributed.impl; + +import java.awt.event.ActionListener; + +/** + * Interface for objects that should have a shutdown sequence. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public interface Shutdownable +{ + public static final String SHUTTING_DOWN = "SHUTTING_DOWN"; + + /** + * Causes this to start to shutdown, and fires a SHUTTING_DOWN event to all + * listeners. + */ + public void shutdown(); + + /** + * This method allows another application to indicate its dependence on this + * to be shutdown. That is, when this's shutdown() method is called, it + * should call the shutdown() method on each component that depends on it. + * + * Implementors and callers should take care not to create an infinite loop + * of shutdown() calls through this method. + * + * @param s + */ + public void addDependentShutdownable(Shutdownable s); + + /** + * This method allows other components to be notified when the shutdown() + * method is called. Listeners will get an ActionEvent whose action command + * is SHUTTING_DOWN. + * + * @param l + */ + public void addShutdownListener(ActionListener l); +} diff --git a/simplCore/src/ecologylab/oodss/distributed/package.html b/simplCore/src/ecologylab/oodss/distributed/package.html index 5ce3fdfa..c237bb3f 100644 --- a/simplCore/src/ecologylab/oodss/distributed/package.html +++ b/simplCore/src/ecologylab/oodss/distributed/package.html @@ -1,7 +1,7 @@ - -Interface Ecology Lab Distributed Computing Services Framework (DCF). - -Enables the definition and provision of socket-based message passing -services that a broad range of applications may wish to utilize, -extend, and offer. - + +Interface Ecology Lab Distributed Computing Services Framework (DCF). + +Enables the definition and provision of socket-based message passing +services that a broad range of applications may wish to utilize, +extend, and offer. + diff --git a/simplCore/src/ecologylab/oodss/distributed/server/DoubleThreadedNIOServer.java b/simplCore/src/ecologylab/oodss/distributed/server/DoubleThreadedNIOServer.java index d6fe76a1..ab4ed20c 100755 --- a/simplCore/src/ecologylab/oodss/distributed/server/DoubleThreadedNIOServer.java +++ b/simplCore/src/ecologylab/oodss/distributed/server/DoubleThreadedNIOServer.java @@ -1,465 +1,465 @@ -/** - * - */ -package ecologylab.oodss.distributed.server; - -import java.io.IOException; -import java.net.BindException; -import java.net.InetAddress; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.channels.SelectionKey; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.util.Arrays; -import java.util.Iterator; - -import ecologylab.collections.Scope; -import ecologylab.generic.CharBufferPool; -import ecologylab.generic.HashMapArrayList; -import ecologylab.generic.StringBuilderPool; -import ecologylab.io.ByteBufferPool; -import ecologylab.net.NetTools; -import ecologylab.oodss.distributed.common.ServerConstants; -import ecologylab.oodss.distributed.common.SessionObjects; -import ecologylab.oodss.distributed.impl.AbstractNIOServer; -import ecologylab.oodss.distributed.impl.NIOServerIOThread; -import ecologylab.oodss.distributed.server.clientsessionmanager.BaseSessionManager; -import ecologylab.oodss.distributed.server.clientsessionmanager.ClientSessionManager; -import ecologylab.oodss.distributed.server.clientsessionmanager.SessionHandle; -import ecologylab.oodss.distributed.server.clientsessionmanager.TCPClientSessionManager; -import ecologylab.oodss.exceptions.BadClientException; -import ecologylab.serialization.SimplTypesScope; - -/** - * A server that uses NIO and two threads (one for handling IO, the other for handling interfacing - * with messages). - * - * Automatically processes and responds to any client RequestMessages. - * - * Subclasses should generally override the generateContextManager hook method, so that they can use - * their own, specific ContextManager in place of the default. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class DoubleThreadedNIOServer extends AbstractNIOServer implements - ServerConstants -{ - protected static InetAddress[] addressToAddresses(InetAddress address) - { - InetAddress[] addresses = - { address }; - return addresses; - } - - public static DoubleThreadedNIOServer getInstance(int portNumber, InetAddress[] inetAddress, - SimplTypesScope requestTranslationScope, Scope applicationObjectScope, - int idleConnectionTimeout, int maxPacketSize) throws IOException, BindException - { - return new DoubleThreadedNIOServer(portNumber, inetAddress, requestTranslationScope, - applicationObjectScope, idleConnectionTimeout, maxPacketSize); - } - - public static DoubleThreadedNIOServer getInstance(int portNumber, InetAddress inetAddress, - SimplTypesScope requestTranslationScope, Scope applicationObjectScope, - int idleConnectionTimeout, int maxPacketSize) throws IOException, BindException - { - InetAddress[] address = - { inetAddress }; - return getInstance(portNumber, address, requestTranslationScope, applicationObjectScope, - idleConnectionTimeout, maxPacketSize); - } - - Thread t = null; - - boolean running = false; - - /** - * Map in which keys are sessionTokens, and values are associated ClientSessionManagers. - */ - private HashMapArrayList clientSessionManagerMap = new HashMapArrayList(); - - /** - * Map in which keys are sessionTokens, and values are associated SessionHandles - */ - private HashMapArrayList clientSessionHandleMap = new HashMapArrayList(); - - private static final Charset ENCODED_CHARSET = Charset - .forName(CHARACTER_ENCODING); - - private static CharsetDecoder DECODER = ENCODED_CHARSET - .newDecoder(); - - protected int maxMessageSize; - - /** - * CharBuffers for use with translating from bytes to chars; may need to support having many - * messages come through at once. - */ - protected CharBufferPool charBufferPool; - - protected ByteBufferPool byteBufferPool; - - protected StringBuilderPool stringBuilderPool; - - /** - * - */ - protected DoubleThreadedNIOServer(int portNumber, InetAddress[] inetAddresses, - SimplTypesScope requestTranslationScope, S applicationObjectScope, - int idleConnectionTimeout, int maxMessageSize) throws IOException, BindException - { - super(portNumber, inetAddresses, requestTranslationScope, applicationObjectScope, - idleConnectionTimeout, maxMessageSize); - - this.maxMessageSize = maxMessageSize + MAX_HTTP_HEADER_LENGTH; - - applicationObjectScope.put(SessionObjects.SESSIONS_MAP, clientSessionHandleMap); - - instantiateBufferPools(this.maxMessageSize); - } - - /** - * @param maxMessageSize - */ - protected void instantiateBufferPools(int maxMessageSize) - { - instantiateBufferPools(4, 4, maxMessageSize); - } - - protected void instantiateBufferPools(int poolSize, int minimumCapicity, int maxMessageSize) - { - this.charBufferPool = new CharBufferPool(poolSize, minimumCapicity, maxMessageSize); - - this.byteBufferPool = new ByteBufferPool(poolSize, minimumCapicity, maxMessageSize); - - this.stringBuilderPool = new StringBuilderPool(poolSize, minimumCapicity, maxMessageSize); - } - /** - * - */ - protected DoubleThreadedNIOServer(int portNumber, InetAddress inetAddress, - SimplTypesScope requestTranslationScope, S applicationObjectScope, - int idleConnectionTimeout, int maxPacketSize) throws IOException, BindException - { - this(portNumber, NetTools.wrapSingleAddress(inetAddress), requestTranslationScope, - applicationObjectScope, idleConnectionTimeout, maxPacketSize); - } - - /** - * Assumes that the server should be running on the local host (including external interfaces) - * with default sizes for everything. - * - * @param portNumber - * - the port number the server will run on. - * @param requestTranslationScope - * - the scope of translation for incoming requests. - * @param applicationObjectScope - * - the application object scope, containing application state objects that messages - * will access and manipulate. - * @throws IOException - * @throws BindException - */ - protected DoubleThreadedNIOServer(int portNumber, SimplTypesScope requestTranslationScope, - S applicationObjectScope) throws BindException, IOException - { - this(portNumber, NetTools.getAllInetAddressesForLocalhost(), requestTranslationScope, - applicationObjectScope, DEFAULT_IDLE_TIMEOUT, DEFAULT_MAX_MESSAGE_LENGTH_CHARS); - } - - @Override - public void processRead(Object sessionToken, NIOServerIOThread base, SelectionKey sk, - ByteBuffer bs, int bytesRead) throws BadClientException - { - if (bytesRead > 0) - { - synchronized (clientSessionManagerMap) - { - TCPClientSessionManager cm = clientSessionManagerMap.get(sessionToken); - - if (cm == null) - { - debug("server creating context manager for " + sessionToken); - - cm = generateContextManager((String) sessionToken, sk, translationScope, - applicationObjectScope); - clientSessionManagerMap.put(sessionToken, cm); - clientSessionHandleMap.put(sessionToken, cm.getHandle()); - } - - try - { - CharBuffer buf = this.charBufferPool.acquire(); - - DECODER.decode(bs, buf, true); - buf.flip(); - cm.processIncomingSequenceBufToQueue(buf); - - buf = this.charBufferPool.release(buf); - } - catch (CharacterCodingException e) - { - e.printStackTrace(); - } - } - - synchronized (this) - { - this.notify(); - } - } - } - - /** - * Hook method to allow changing the ContextManager to enable specific extra functionality. - * - * @param token - * @param sc - * @param translationScopeIn - * @param registryIn - * @return - */ - @Override - protected TCPClientSessionManager generateContextManager(String sessionId, SelectionKey sk, - SimplTypesScope translationScopeIn, Scope registryIn) - { - return new ClientSessionManager(sessionId, maxMessageSize, this.getBackend(), this, sk, - translationScopeIn, registryIn); - } - - @Override - public void run() - { - Iterator contextIter; - - while (running) - { - synchronized (clientSessionManagerMap) - { - contextIter = clientSessionManagerMap.values().iterator(); - - // process all of the messages in the queues - while (contextIter.hasNext()) - { - TCPClientSessionManager cm = contextIter.next(); - - try - { - cm.processAllMessagesAndSendResponses(); - } - catch (BadClientException e) - { - // Handle BadClientException! -- remove it - error(e.getMessage()); - - // invalidate the manager's key - this.getBackend().setPendingInvalidate(cm.getSocketKey(), true); - - // remove the manager from the collection - contextIter.remove(); - } - } - } - - // sleep until notified of new messages - synchronized (this) - { - try - { - wait(); - } - catch (InterruptedException e) - { - e.printStackTrace(); - Thread.interrupted(); - } - } - } - } - - /** - * @see ecologylab.generic.StartAndStoppable#start() - */ - @Override - public void start() - { - running = true; - - if (t == null) - { - t = new Thread(this); - } - - t.start(); - - super.start(); - } - - /** - * @see ecologylab.generic.StartAndStoppable#stop() - */ - @Override - public void stop() - { - debug("Server stopping."); - running = false; - synchronized (this) - { - this.notify(); - synchronized (t) - { - t = null; - } - } - super.stop(); - } - - /** - * @see ecologylab.oodss.distributed.impl.Shutdownable#shutdown() - */ - @Override - public void shutdown() - { - // TODO Auto-generated method stub - - } - - /** - * @see ecologylab.oodss.distributed.server.NIOServerProcessor#invalidate(java.lang.Object, - * ecologylab.oodss.distributed.impl.NIOServerIOThread, java.nio.channels.SocketChannel) - */ - @Override - public boolean invalidate(String sessionId, boolean forcePermanent) - { - BaseSessionManager cm = clientSessionManagerMap.get(sessionId); - - // figure out if the disconnect is permanent; will be permanent if forcing - // (usually bad client), if there is no context manager (client never sent - // data), or if the client manager says it is invalidating (client - // disconnected properly) - boolean permanent = (forcePermanent ? true : (cm == null ? true : cm.isInvalidating())); - - // get the context manager... - if (permanent) - { - synchronized (clientSessionManagerMap) - { // ...if this session will not be restored, remove the context - // manager - clientSessionManagerMap.remove(sessionId); - clientSessionHandleMap.remove(sessionId); - } - } - - if (cm != null) - { - /* - * if we've gotten here, then the client has disconnected already, no reason to deal w/ the - * remaining messages // finish what the context manager was working on while - * (cm.isMessageWaiting()) { try { cm.processAllMessagesAndSendResponses(); } catch - * (BadClientException e) { e.printStackTrace(); } } - */ - cm.shutdown(); - } - - return permanent; - } - - /** - * Attempts to switch the ContextManager for a SocketChannel. oldId indicates the session id that - * was used for the connection previously (in order to find the correct ContextManager) and - * newContextManager is the recently-created (and now, no longer necessary) ContextManager for the - * connection. - * - * @param oldId - * @param newContextManager - * @return true if the restore was successful, false if it was not. - */ - @Override - public boolean restoreContextManagerFromSessionId(String oldSessionId, - BaseSessionManager newContextManager) - { - debug("attempting to restore old session..."); - - TCPClientSessionManager oldContextManager; - - synchronized (clientSessionManagerMap) - { - oldContextManager = this.clientSessionManagerMap.get(oldSessionId); - } - if (oldContextManager == null) - { // cannot restore old context - debug("restore failed."); - return false; - } - else - { - oldContextManager.setSocket(newContextManager.getSocketKey()); - - synchronized (clientSessionManagerMap) - { - /* remove pointers to new session manager since we're using the old one */ - this.clientSessionManagerMap.remove(newContextManager.getSessionId()); - this.clientSessionHandleMap.remove(newContextManager.getSessionId()); - } - - this.getBackend().debug("old session restored!"); - return true; - } - } - - /** - * - * @return status of server in boolean - */ - public boolean isRunning() - { - return running; - } - - @Override - protected void shutdownImpl() - { - // TODO Auto-generated method stub - - } - - /** - * Utility method for dynamically name TranslationScopes. - * - * @param inetAddresses - * @param portNumber - * @return - */ - protected static String connectionTscopeName(InetAddress[] inetAddresses, int portNumber) - { - return "double_threaded_logging " + inetAddresses[0].toString() + ":" + portNumber; - } - - @Override - public ByteBufferPool getSharedByteBufferPool() - { - return byteBufferPool; - } - - @Override - public CharBufferPool getSharedCharBufferPool() - { - return charBufferPool; - } - - @Override - public StringBuilderPool getSharedStringBuilderPool() - { - return stringBuilderPool; - } - - @Override - public void increaseSharedBufferPoolSize(int newCapacity) { - char[] tempCharBufferArray = Arrays.copyOf(charBufferPool.acquire().array(), charBufferPool.acquire().array().length); - byte[] tempBtyeBufferArray = Arrays.copyOf(byteBufferPool.acquire().array(), byteBufferPool.acquire().array().length); - instantiateBufferPools(newCapacity); - System.arraycopy(tempCharBufferArray, 0, charBufferPool.acquire().array(), 0, tempCharBufferArray.length); - System.arraycopy(tempBtyeBufferArray, 0, byteBufferPool.acquire().array(), 0, tempBtyeBufferArray.length); - } -} +/** + * + */ +package ecologylab.oodss.distributed.server; + +import java.io.IOException; +import java.net.BindException; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.channels.SelectionKey; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.util.Arrays; +import java.util.Iterator; + +import ecologylab.collections.Scope; +import ecologylab.generic.CharBufferPool; +import ecologylab.generic.HashMapArrayList; +import ecologylab.generic.StringBuilderPool; +import ecologylab.io.ByteBufferPool; +import ecologylab.net.NetTools; +import ecologylab.oodss.distributed.common.ServerConstants; +import ecologylab.oodss.distributed.common.SessionObjects; +import ecologylab.oodss.distributed.impl.AbstractNIOServer; +import ecologylab.oodss.distributed.impl.NIOServerIOThread; +import ecologylab.oodss.distributed.server.clientsessionmanager.BaseSessionManager; +import ecologylab.oodss.distributed.server.clientsessionmanager.ClientSessionManager; +import ecologylab.oodss.distributed.server.clientsessionmanager.SessionHandle; +import ecologylab.oodss.distributed.server.clientsessionmanager.TCPClientSessionManager; +import ecologylab.oodss.exceptions.BadClientException; +import ecologylab.serialization.SimplTypesScope; + +/** + * A server that uses NIO and two threads (one for handling IO, the other for handling interfacing + * with messages). + * + * Automatically processes and responds to any client RequestMessages. + * + * Subclasses should generally override the generateContextManager hook method, so that they can use + * their own, specific ContextManager in place of the default. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class DoubleThreadedNIOServer extends AbstractNIOServer implements + ServerConstants +{ + protected static InetAddress[] addressToAddresses(InetAddress address) + { + InetAddress[] addresses = + { address }; + return addresses; + } + + public static DoubleThreadedNIOServer getInstance(int portNumber, InetAddress[] inetAddress, + SimplTypesScope requestTranslationScope, Scope applicationObjectScope, + int idleConnectionTimeout, int maxPacketSize) throws IOException, BindException + { + return new DoubleThreadedNIOServer(portNumber, inetAddress, requestTranslationScope, + applicationObjectScope, idleConnectionTimeout, maxPacketSize); + } + + public static DoubleThreadedNIOServer getInstance(int portNumber, InetAddress inetAddress, + SimplTypesScope requestTranslationScope, Scope applicationObjectScope, + int idleConnectionTimeout, int maxPacketSize) throws IOException, BindException + { + InetAddress[] address = + { inetAddress }; + return getInstance(portNumber, address, requestTranslationScope, applicationObjectScope, + idleConnectionTimeout, maxPacketSize); + } + + Thread t = null; + + boolean running = false; + + /** + * Map in which keys are sessionTokens, and values are associated ClientSessionManagers. + */ + private HashMapArrayList clientSessionManagerMap = new HashMapArrayList(); + + /** + * Map in which keys are sessionTokens, and values are associated SessionHandles + */ + private HashMapArrayList clientSessionHandleMap = new HashMapArrayList(); + + private static final Charset ENCODED_CHARSET = Charset + .forName(CHARACTER_ENCODING); + + private static CharsetDecoder DECODER = ENCODED_CHARSET + .newDecoder(); + + protected int maxMessageSize; + + /** + * CharBuffers for use with translating from bytes to chars; may need to support having many + * messages come through at once. + */ + protected CharBufferPool charBufferPool; + + protected ByteBufferPool byteBufferPool; + + protected StringBuilderPool stringBuilderPool; + + /** + * + */ + protected DoubleThreadedNIOServer(int portNumber, InetAddress[] inetAddresses, + SimplTypesScope requestTranslationScope, S applicationObjectScope, + int idleConnectionTimeout, int maxMessageSize) throws IOException, BindException + { + super(portNumber, inetAddresses, requestTranslationScope, applicationObjectScope, + idleConnectionTimeout, maxMessageSize); + + this.maxMessageSize = maxMessageSize + MAX_HTTP_HEADER_LENGTH; + + applicationObjectScope.put(SessionObjects.SESSIONS_MAP, clientSessionHandleMap); + + instantiateBufferPools(this.maxMessageSize); + } + + /** + * @param maxMessageSize + */ + protected void instantiateBufferPools(int maxMessageSize) + { + instantiateBufferPools(4, 4, maxMessageSize); + } + + protected void instantiateBufferPools(int poolSize, int minimumCapicity, int maxMessageSize) + { + this.charBufferPool = new CharBufferPool(poolSize, minimumCapicity, maxMessageSize); + + this.byteBufferPool = new ByteBufferPool(poolSize, minimumCapicity, maxMessageSize); + + this.stringBuilderPool = new StringBuilderPool(poolSize, minimumCapicity, maxMessageSize); + } + /** + * + */ + protected DoubleThreadedNIOServer(int portNumber, InetAddress inetAddress, + SimplTypesScope requestTranslationScope, S applicationObjectScope, + int idleConnectionTimeout, int maxPacketSize) throws IOException, BindException + { + this(portNumber, NetTools.wrapSingleAddress(inetAddress), requestTranslationScope, + applicationObjectScope, idleConnectionTimeout, maxPacketSize); + } + + /** + * Assumes that the server should be running on the local host (including external interfaces) + * with default sizes for everything. + * + * @param portNumber + * - the port number the server will run on. + * @param requestTranslationScope + * - the scope of translation for incoming requests. + * @param applicationObjectScope + * - the application object scope, containing application state objects that messages + * will access and manipulate. + * @throws IOException + * @throws BindException + */ + protected DoubleThreadedNIOServer(int portNumber, SimplTypesScope requestTranslationScope, + S applicationObjectScope) throws BindException, IOException + { + this(portNumber, NetTools.getAllInetAddressesForLocalhost(), requestTranslationScope, + applicationObjectScope, DEFAULT_IDLE_TIMEOUT, DEFAULT_MAX_MESSAGE_LENGTH_CHARS); + } + + @Override + public void processRead(Object sessionToken, NIOServerIOThread base, SelectionKey sk, + ByteBuffer bs, int bytesRead) throws BadClientException + { + if (bytesRead > 0) + { + synchronized (clientSessionManagerMap) + { + TCPClientSessionManager cm = clientSessionManagerMap.get(sessionToken); + + if (cm == null) + { + debug("server creating context manager for " + sessionToken); + + cm = generateContextManager((String) sessionToken, sk, translationScope, + applicationObjectScope); + clientSessionManagerMap.put(sessionToken, cm); + clientSessionHandleMap.put(sessionToken, cm.getHandle()); + } + + try + { + CharBuffer buf = this.charBufferPool.acquire(); + + DECODER.decode(bs, buf, true); + buf.flip(); + cm.processIncomingSequenceBufToQueue(buf); + + buf = this.charBufferPool.release(buf); + } + catch (CharacterCodingException e) + { + e.printStackTrace(); + } + } + + synchronized (this) + { + this.notify(); + } + } + } + + /** + * Hook method to allow changing the ContextManager to enable specific extra functionality. + * + * @param token + * @param sc + * @param translationScopeIn + * @param registryIn + * @return + */ + @Override + protected TCPClientSessionManager generateContextManager(String sessionId, SelectionKey sk, + SimplTypesScope translationScopeIn, Scope registryIn) + { + return new ClientSessionManager(sessionId, maxMessageSize, this.getBackend(), this, sk, + translationScopeIn, registryIn); + } + + @Override + public void run() + { + Iterator contextIter; + + while (running) + { + synchronized (clientSessionManagerMap) + { + contextIter = clientSessionManagerMap.values().iterator(); + + // process all of the messages in the queues + while (contextIter.hasNext()) + { + TCPClientSessionManager cm = contextIter.next(); + + try + { + cm.processAllMessagesAndSendResponses(); + } + catch (BadClientException e) + { + // Handle BadClientException! -- remove it + error(e.getMessage()); + + // invalidate the manager's key + this.getBackend().setPendingInvalidate(cm.getSocketKey(), true); + + // remove the manager from the collection + contextIter.remove(); + } + } + } + + // sleep until notified of new messages + synchronized (this) + { + try + { + wait(); + } + catch (InterruptedException e) + { + e.printStackTrace(); + Thread.interrupted(); + } + } + } + } + + /** + * @see ecologylab.generic.StartAndStoppable#start() + */ + @Override + public void start() + { + running = true; + + if (t == null) + { + t = new Thread(this); + } + + t.start(); + + super.start(); + } + + /** + * @see ecologylab.generic.StartAndStoppable#stop() + */ + @Override + public void stop() + { + debug("Server stopping."); + running = false; + synchronized (this) + { + this.notify(); + synchronized (t) + { + t = null; + } + } + super.stop(); + } + + /** + * @see ecologylab.oodss.distributed.impl.Shutdownable#shutdown() + */ + @Override + public void shutdown() + { + // TODO Auto-generated method stub + + } + + /** + * @see ecologylab.oodss.distributed.server.NIOServerProcessor#invalidate(java.lang.Object, + * ecologylab.oodss.distributed.impl.NIOServerIOThread, java.nio.channels.SocketChannel) + */ + @Override + public boolean invalidate(String sessionId, boolean forcePermanent) + { + BaseSessionManager cm = clientSessionManagerMap.get(sessionId); + + // figure out if the disconnect is permanent; will be permanent if forcing + // (usually bad client), if there is no context manager (client never sent + // data), or if the client manager says it is invalidating (client + // disconnected properly) + boolean permanent = (forcePermanent ? true : (cm == null ? true : cm.isInvalidating())); + + // get the context manager... + if (permanent) + { + synchronized (clientSessionManagerMap) + { // ...if this session will not be restored, remove the context + // manager + clientSessionManagerMap.remove(sessionId); + clientSessionHandleMap.remove(sessionId); + } + } + + if (cm != null) + { + /* + * if we've gotten here, then the client has disconnected already, no reason to deal w/ the + * remaining messages // finish what the context manager was working on while + * (cm.isMessageWaiting()) { try { cm.processAllMessagesAndSendResponses(); } catch + * (BadClientException e) { e.printStackTrace(); } } + */ + cm.shutdown(); + } + + return permanent; + } + + /** + * Attempts to switch the ContextManager for a SocketChannel. oldId indicates the session id that + * was used for the connection previously (in order to find the correct ContextManager) and + * newContextManager is the recently-created (and now, no longer necessary) ContextManager for the + * connection. + * + * @param oldId + * @param newContextManager + * @return true if the restore was successful, false if it was not. + */ + @Override + public boolean restoreContextManagerFromSessionId(String oldSessionId, + BaseSessionManager newContextManager) + { + debug("attempting to restore old session..."); + + TCPClientSessionManager oldContextManager; + + synchronized (clientSessionManagerMap) + { + oldContextManager = this.clientSessionManagerMap.get(oldSessionId); + } + if (oldContextManager == null) + { // cannot restore old context + debug("restore failed."); + return false; + } + else + { + oldContextManager.setSocket(newContextManager.getSocketKey()); + + synchronized (clientSessionManagerMap) + { + /* remove pointers to new session manager since we're using the old one */ + this.clientSessionManagerMap.remove(newContextManager.getSessionId()); + this.clientSessionHandleMap.remove(newContextManager.getSessionId()); + } + + this.getBackend().debug("old session restored!"); + return true; + } + } + + /** + * + * @return status of server in boolean + */ + public boolean isRunning() + { + return running; + } + + @Override + protected void shutdownImpl() + { + // TODO Auto-generated method stub + + } + + /** + * Utility method for dynamically name TranslationScopes. + * + * @param inetAddresses + * @param portNumber + * @return + */ + protected static String connectionTscopeName(InetAddress[] inetAddresses, int portNumber) + { + return "double_threaded_logging " + inetAddresses[0].toString() + ":" + portNumber; + } + + @Override + public ByteBufferPool getSharedByteBufferPool() + { + return byteBufferPool; + } + + @Override + public CharBufferPool getSharedCharBufferPool() + { + return charBufferPool; + } + + @Override + public StringBuilderPool getSharedStringBuilderPool() + { + return stringBuilderPool; + } + + @Override + public void increaseSharedBufferPoolSize(int newCapacity) { + char[] tempCharBufferArray = Arrays.copyOf(charBufferPool.acquire().array(), charBufferPool.acquire().array().length); + byte[] tempBtyeBufferArray = Arrays.copyOf(byteBufferPool.acquire().array(), byteBufferPool.acquire().array().length); + instantiateBufferPools(newCapacity); + System.arraycopy(tempCharBufferArray, 0, charBufferPool.acquire().array(), 0, tempCharBufferArray.length); + System.arraycopy(tempBtyeBufferArray, 0, byteBufferPool.acquire().array(), 0, tempBtyeBufferArray.length); + } +} diff --git a/simplCore/src/ecologylab/oodss/distributed/server/NIOServerDataReader.java b/simplCore/src/ecologylab/oodss/distributed/server/NIOServerDataReader.java index 0a8454b3..55324f75 100644 --- a/simplCore/src/ecologylab/oodss/distributed/server/NIOServerDataReader.java +++ b/simplCore/src/ecologylab/oodss/distributed/server/NIOServerDataReader.java @@ -1,33 +1,33 @@ -/** - * - */ -package ecologylab.oodss.distributed.server; - -import java.nio.ByteBuffer; -import java.nio.channels.SelectionKey; - -import ecologylab.oodss.distributed.impl.NIOServerIOThread; -import ecologylab.oodss.exceptions.BadClientException; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public interface NIOServerDataReader extends NIOServerProcessor -{ - - /** - * Handles passing incoming bytes to the appropriate ClientSessionManager. - * - * @param sessionToken Identifies which ClientSessionManager to pass the bytes to. - * If this is the first time a new ClientSessionManger will be constructed. - * @param base - * @param sk - * @param bs - * @param bytesRead - * @throws BadClientException - */ - public abstract void processRead(Object sessionToken, NIOServerIOThread base, SelectionKey sk, - ByteBuffer bs, int bytesRead) throws BadClientException; - +/** + * + */ +package ecologylab.oodss.distributed.server; + +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; + +import ecologylab.oodss.distributed.impl.NIOServerIOThread; +import ecologylab.oodss.exceptions.BadClientException; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public interface NIOServerDataReader extends NIOServerProcessor +{ + + /** + * Handles passing incoming bytes to the appropriate ClientSessionManager. + * + * @param sessionToken Identifies which ClientSessionManager to pass the bytes to. + * If this is the first time a new ClientSessionManger will be constructed. + * @param base + * @param sk + * @param bs + * @param bytesRead + * @throws BadClientException + */ + public abstract void processRead(Object sessionToken, NIOServerIOThread base, SelectionKey sk, + ByteBuffer bs, int bytesRead) throws BadClientException; + } \ No newline at end of file diff --git a/simplCore/src/ecologylab/oodss/distributed/server/NIOServerProcessor.java b/simplCore/src/ecologylab/oodss/distributed/server/NIOServerProcessor.java index 827ba469..076196e0 100755 --- a/simplCore/src/ecologylab/oodss/distributed/server/NIOServerProcessor.java +++ b/simplCore/src/ecologylab/oodss/distributed/server/NIOServerProcessor.java @@ -1,52 +1,52 @@ -/** - * - */ -package ecologylab.oodss.distributed.server; - -import ecologylab.generic.CharBufferPool; -import ecologylab.generic.StartAndStoppable; -import ecologylab.generic.StringBuilderPool; -import ecologylab.io.ByteBufferPool; -import ecologylab.oodss.distributed.server.clientsessionmanager.BaseSessionManager; - -/** - * An interface indicating necessary functionality for a server so that it can properly service - * ContextManagers. - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public interface NIOServerProcessor extends StartAndStoppable -{ - /** - * Performs any internal actions that should be taken whenever a client is disconnected. - * - * @param sessionId - * the identifier for the client's connection (key.attachment(), normally) - * @param forcePermanent - * TODO - * @return true if the client is permanently disconnecting - */ - public boolean invalidate(String sessionId, boolean forcePermanent); - - /** - * Attempts to switch the ContextManager for a SocketChannel. oldId indicates the session id that - * was used for the connection previously (in order to find the correct ContextManager) and - * newContextManager is the recently-created (and now, no longer necessary) ContextManager for the - * connection. - * - * @param oldId - * @param newContextManager - * @return true if the restore was successful, false if it was not. - */ - public boolean restoreContextManagerFromSessionId(String oldId, - BaseSessionManager newContextManager); - - public ByteBufferPool getSharedByteBufferPool(); - - public CharBufferPool getSharedCharBufferPool(); - - public StringBuilderPool getSharedStringBuilderPool(); - - public void increaseSharedBufferPoolSize(int newCapacity); -} +/** + * + */ +package ecologylab.oodss.distributed.server; + +import ecologylab.generic.CharBufferPool; +import ecologylab.generic.StartAndStoppable; +import ecologylab.generic.StringBuilderPool; +import ecologylab.io.ByteBufferPool; +import ecologylab.oodss.distributed.server.clientsessionmanager.BaseSessionManager; + +/** + * An interface indicating necessary functionality for a server so that it can properly service + * ContextManagers. + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public interface NIOServerProcessor extends StartAndStoppable +{ + /** + * Performs any internal actions that should be taken whenever a client is disconnected. + * + * @param sessionId + * the identifier for the client's connection (key.attachment(), normally) + * @param forcePermanent + * TODO + * @return true if the client is permanently disconnecting + */ + public boolean invalidate(String sessionId, boolean forcePermanent); + + /** + * Attempts to switch the ContextManager for a SocketChannel. oldId indicates the session id that + * was used for the connection previously (in order to find the correct ContextManager) and + * newContextManager is the recently-created (and now, no longer necessary) ContextManager for the + * connection. + * + * @param oldId + * @param newContextManager + * @return true if the restore was successful, false if it was not. + */ + public boolean restoreContextManagerFromSessionId(String oldId, + BaseSessionManager newContextManager); + + public ByteBufferPool getSharedByteBufferPool(); + + public CharBufferPool getSharedCharBufferPool(); + + public StringBuilderPool getSharedStringBuilderPool(); + + public void increaseSharedBufferPoolSize(int newCapacity); +} diff --git a/simplCore/src/ecologylab/oodss/distributed/server/ServerMessages.java b/simplCore/src/ecologylab/oodss/distributed/server/ServerMessages.java index ec40a442..d00a7b2e 100644 --- a/simplCore/src/ecologylab/oodss/distributed/server/ServerMessages.java +++ b/simplCore/src/ecologylab/oodss/distributed/server/ServerMessages.java @@ -1,11 +1,11 @@ -package ecologylab.oodss.distributed.server; - -public interface ServerMessages { - - //This is called when adding a server object that the class that implements this will save - public void putServerObject(Object o); - - public String getAPushFromWebSocket(String s, String sessionId); - - public void newClientAdded(String sessionId); -} +package ecologylab.oodss.distributed.server; + +public interface ServerMessages { + + //This is called when adding a server object that the class that implements this will save + public void putServerObject(Object o); + + public String getAPushFromWebSocket(String s, String sessionId); + + public void newClientAdded(String sessionId); +} diff --git a/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/BaseSessionManager.java b/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/BaseSessionManager.java index dfecf38d..071bea1f 100644 --- a/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/BaseSessionManager.java +++ b/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/BaseSessionManager.java @@ -1,284 +1,284 @@ -/** - * - */ -package ecologylab.oodss.distributed.server.clientsessionmanager; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.channels.SelectionKey; - -import ecologylab.collections.Scope; -import ecologylab.generic.Debug; -import ecologylab.oodss.distributed.server.NIOServerProcessor; -import ecologylab.oodss.messages.BadSemanticContentResponse; -import ecologylab.oodss.messages.InitConnectionRequest; -import ecologylab.oodss.messages.InitConnectionResponse; -import ecologylab.oodss.messages.RequestMessage; -import ecologylab.oodss.messages.ResponseMessage; -import ecologylab.oodss.messages.UpdateMessage; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public abstract class BaseSessionManager extends Debug -{ - - /** - * Indicates whether or not one or more messages are queued for execution by this ContextManager. - */ - protected boolean messageWaiting = false; - - /** - * Session handle available to use by clients - */ - protected SessionHandle handle; - - /** - * sessionId uniquely identifies this ContextManager. It is used to restore the state of a lost - * connection. - */ - protected String sessionId = null; - - protected S localScope; - - protected long lastActivity = System.currentTimeMillis(); - - /** The selection key for this context manager. */ - protected SelectionKey socketKey; - - /** - * The frontend for the server that is running the ContextManager. This is needed in case the - * client attempts to restore a session, in which case the frontend must be queried for the old - * ContextManager. - */ - protected NIOServerProcessor frontend = null; - - /** - * Indicates whether the first request message has been received. The first request may be an - * InitConnection, which has special properties. - */ - protected boolean initialized = false; - - /** - * Used for disconnecting. A disconnect message will call the setInvalidating method, which will - * set this value to true. The processing method will set itself as pending invalidation after it - * has produces the bytes for the response to the disconnect message. - */ - private boolean invalidating = false; - - public static final String SESSION_ID = "SESSION_ID"; - - public static final String CLIENT_MANAGER = "CLIENT_MANAGER"; - - /** - * - */ - public BaseSessionManager(String sessionId, NIOServerProcessor frontend, SelectionKey socket, - PARENT baseScope) - { - super(); - - this.frontend = frontend; - this.socketKey = socket; - this.sessionId = sessionId; - - this.localScope = generateContextScope(baseScope); - - this.localScope.put(SESSION_ID, sessionId); - this.localScope.put(CLIENT_MANAGER, this); - } - - /** - * Provides the context scope for the client attached to this session manager. The base - * implementation instantiates a new Scope with baseScope as the argument. Subclasses may - * provide specific subclasses of Scope as the return value. They must still incorporate baseScope - * as the lexically chained application object scope. - * - * @param baseScope - * @return - */ - protected S generateContextScope(PARENT baseScope) - { - return (S) new Scope(baseScope); - } - - /** - * Appends the sender's IP address to the incoming message and calls performService on the given - * RequestMessage using the local ObjectRegistry. - * - * performService(RequestMessage) may be overridden by subclasses to provide more specialized - * functionality. Generally, overrides should then call super.performService(RequestMessage) so - * that the IP address is appended to the message. - * - * @param requestMessage - * @return - */ - protected ResponseMessage performService(RequestMessage requestMessage, InetAddress address) - { - requestMessage.setSender(address); - - try - { - return requestMessage.performService(localScope); - } - catch (Exception e) - { - e.printStackTrace(); - - return new BadSemanticContentResponse("The request, " - + requestMessage.toString() - + " caused an exception on the server."); - } - } - - /** - * Calls RequestMessage.performService(Scope) and returns the result. - * - * @param request - * - the request message to process. - */ - protected ResponseMessage processRequest(RequestMessage request, InetAddress address) - { - this.lastActivity = System.currentTimeMillis(); - - ResponseMessage response = null; - - if (request == null) - { - debug("No request."); - } - else - { - if (!isInitialized()) - { - // special processing for InitConnectionRequest - if (request instanceof InitConnectionRequest) - { - String incomingSessionId = ((InitConnectionRequest) request).getSessionId(); - - if (incomingSessionId == null) - { // client is not expecting an old ContextManager - response = new InitConnectionResponse(this.sessionId); - } - else - { // client is expecting an old ContextManager - if (frontend.restoreContextManagerFromSessionId(incomingSessionId, this)) - { - response = new InitConnectionResponse(incomingSessionId); - } - else - { - response = new InitConnectionResponse(this.sessionId); - } - } - - initialized = true; - } - } - else - { - // perform the service being requested - response = performService(request, address); - } - - if (response == null) - { - debug("context manager did not produce a response message."); - } - } - - return response; - } - - /** - * Indicates the last System timestamp was when the ContextManager had any activity. - * - * @return the last System timestamp indicating when the ContextManager had any activity. - */ - public final long getLastActivity() - { - return lastActivity; - } - - /** - * @return the socket - */ - public SelectionKey getSocketKey() - { - return socketKey; - } - - /** - * Indicates whether there are any messages queued up to be processed. - * - * isMessageWaiting() should be overridden if getNextRequest() is overridden so that it properly - * reflects the way that getNextRequest() works; it may also be important to override - * enqueueRequest(). - * - * @return true if getNextRequest() can return a value, false if it cannot. - */ - public boolean isMessageWaiting() - { - return messageWaiting; - } - - /** - * Indicates whether or not this context manager has been initialized. Normally, this means that - * it has shared a session id with the client. - * - * @return - */ - public boolean isInitialized() - { - return initialized; - } - - /** - * @param invalidating - * the invalidating to set - */ - public void setInvalidating(boolean invalidating) - { - this.invalidating = invalidating; - } - - /** - * Indicates whether or not the client manager is expecting a disconnect. If this method returns - * true, then this client manager should be disposed of when the client disconnects; otherwise, it - * should be retained until the client comes back, or the client managers are cleaned up. - * - * @return true if the client manager is expecting the client to disconnect, false otherwise - */ - public boolean isInvalidating() - { - return invalidating; - } - - public abstract void sendUpdateToClient(UpdateMessage update); - - /** - * @return the address - */ - public abstract InetSocketAddress getAddress(); - - public String getSessionId() - { - return this.sessionId; - } - - public Scope getScope() - { - return this.localScope; - } - - /** - * Hook method for having shutdown behavior. - * - * This method is called whenever the server is closing down the connection to this client. - */ - public void shutdown() - { - - } +/** + * + */ +package ecologylab.oodss.distributed.server.clientsessionmanager; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.channels.SelectionKey; + +import ecologylab.collections.Scope; +import ecologylab.generic.Debug; +import ecologylab.oodss.distributed.server.NIOServerProcessor; +import ecologylab.oodss.messages.BadSemanticContentResponse; +import ecologylab.oodss.messages.InitConnectionRequest; +import ecologylab.oodss.messages.InitConnectionResponse; +import ecologylab.oodss.messages.RequestMessage; +import ecologylab.oodss.messages.ResponseMessage; +import ecologylab.oodss.messages.UpdateMessage; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public abstract class BaseSessionManager extends Debug +{ + + /** + * Indicates whether or not one or more messages are queued for execution by this ContextManager. + */ + protected boolean messageWaiting = false; + + /** + * Session handle available to use by clients + */ + protected SessionHandle handle; + + /** + * sessionId uniquely identifies this ContextManager. It is used to restore the state of a lost + * connection. + */ + protected String sessionId = null; + + protected S localScope; + + protected long lastActivity = System.currentTimeMillis(); + + /** The selection key for this context manager. */ + protected SelectionKey socketKey; + + /** + * The frontend for the server that is running the ContextManager. This is needed in case the + * client attempts to restore a session, in which case the frontend must be queried for the old + * ContextManager. + */ + protected NIOServerProcessor frontend = null; + + /** + * Indicates whether the first request message has been received. The first request may be an + * InitConnection, which has special properties. + */ + protected boolean initialized = false; + + /** + * Used for disconnecting. A disconnect message will call the setInvalidating method, which will + * set this value to true. The processing method will set itself as pending invalidation after it + * has produces the bytes for the response to the disconnect message. + */ + private boolean invalidating = false; + + public static final String SESSION_ID = "SESSION_ID"; + + public static final String CLIENT_MANAGER = "CLIENT_MANAGER"; + + /** + * + */ + public BaseSessionManager(String sessionId, NIOServerProcessor frontend, SelectionKey socket, + PARENT baseScope) + { + super(); + + this.frontend = frontend; + this.socketKey = socket; + this.sessionId = sessionId; + + this.localScope = generateContextScope(baseScope); + + this.localScope.put(SESSION_ID, sessionId); + this.localScope.put(CLIENT_MANAGER, this); + } + + /** + * Provides the context scope for the client attached to this session manager. The base + * implementation instantiates a new Scope with baseScope as the argument. Subclasses may + * provide specific subclasses of Scope as the return value. They must still incorporate baseScope + * as the lexically chained application object scope. + * + * @param baseScope + * @return + */ + protected S generateContextScope(PARENT baseScope) + { + return (S) new Scope(baseScope); + } + + /** + * Appends the sender's IP address to the incoming message and calls performService on the given + * RequestMessage using the local ObjectRegistry. + * + * performService(RequestMessage) may be overridden by subclasses to provide more specialized + * functionality. Generally, overrides should then call super.performService(RequestMessage) so + * that the IP address is appended to the message. + * + * @param requestMessage + * @return + */ + protected ResponseMessage performService(RequestMessage requestMessage, InetAddress address) + { + requestMessage.setSender(address); + + try + { + return requestMessage.performService(localScope); + } + catch (Exception e) + { + e.printStackTrace(); + + return new BadSemanticContentResponse("The request, " + + requestMessage.toString() + + " caused an exception on the server."); + } + } + + /** + * Calls RequestMessage.performService(Scope) and returns the result. + * + * @param request + * - the request message to process. + */ + protected ResponseMessage processRequest(RequestMessage request, InetAddress address) + { + this.lastActivity = System.currentTimeMillis(); + + ResponseMessage response = null; + + if (request == null) + { + debug("No request."); + } + else + { + if (!isInitialized()) + { + // special processing for InitConnectionRequest + if (request instanceof InitConnectionRequest) + { + String incomingSessionId = ((InitConnectionRequest) request).getSessionId(); + + if (incomingSessionId == null) + { // client is not expecting an old ContextManager + response = new InitConnectionResponse(this.sessionId); + } + else + { // client is expecting an old ContextManager + if (frontend.restoreContextManagerFromSessionId(incomingSessionId, this)) + { + response = new InitConnectionResponse(incomingSessionId); + } + else + { + response = new InitConnectionResponse(this.sessionId); + } + } + + initialized = true; + } + } + else + { + // perform the service being requested + response = performService(request, address); + } + + if (response == null) + { + debug("context manager did not produce a response message."); + } + } + + return response; + } + + /** + * Indicates the last System timestamp was when the ContextManager had any activity. + * + * @return the last System timestamp indicating when the ContextManager had any activity. + */ + public final long getLastActivity() + { + return lastActivity; + } + + /** + * @return the socket + */ + public SelectionKey getSocketKey() + { + return socketKey; + } + + /** + * Indicates whether there are any messages queued up to be processed. + * + * isMessageWaiting() should be overridden if getNextRequest() is overridden so that it properly + * reflects the way that getNextRequest() works; it may also be important to override + * enqueueRequest(). + * + * @return true if getNextRequest() can return a value, false if it cannot. + */ + public boolean isMessageWaiting() + { + return messageWaiting; + } + + /** + * Indicates whether or not this context manager has been initialized. Normally, this means that + * it has shared a session id with the client. + * + * @return + */ + public boolean isInitialized() + { + return initialized; + } + + /** + * @param invalidating + * the invalidating to set + */ + public void setInvalidating(boolean invalidating) + { + this.invalidating = invalidating; + } + + /** + * Indicates whether or not the client manager is expecting a disconnect. If this method returns + * true, then this client manager should be disposed of when the client disconnects; otherwise, it + * should be retained until the client comes back, or the client managers are cleaned up. + * + * @return true if the client manager is expecting the client to disconnect, false otherwise + */ + public boolean isInvalidating() + { + return invalidating; + } + + public abstract void sendUpdateToClient(UpdateMessage update); + + /** + * @return the address + */ + public abstract InetSocketAddress getAddress(); + + public String getSessionId() + { + return this.sessionId; + } + + public Scope getScope() + { + return this.localScope; + } + + /** + * Hook method for having shutdown behavior. + * + * This method is called whenever the server is closing down the connection to this client. + */ + public void shutdown() + { + + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/ClientSessionManager.java b/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/ClientSessionManager.java index 376ff85b..9a5f44b6 100644 --- a/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/ClientSessionManager.java +++ b/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/ClientSessionManager.java @@ -1,163 +1,163 @@ -package ecologylab.oodss.distributed.server.clientsessionmanager; - -import java.nio.channels.SelectionKey; - -import ecologylab.collections.Scope; -import ecologylab.oodss.distributed.common.ServerConstants; -import ecologylab.oodss.distributed.impl.NIOServerIOThread; -import ecologylab.oodss.distributed.server.NIOServerProcessor; -import ecologylab.oodss.messages.RequestMessage; -import ecologylab.oodss.messages.ResponseMessage; -import ecologylab.oodss.messages.UpdateMessage; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * Stores information about the connection context for the client on the server. Should be extended - * for more specific implementations. Handles accumulating incoming messages and translating them - * into RequestMessage objects, as well as the ability to perform the messages' services and send - * their responses. - * - * Generally, this class can be driven by one or more threads, depending on the desired - * functionality. - * - * On a server, there will be one ContextManager for each client connection. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class ClientSessionManager extends TCPClientSessionManager implements ServerConstants -{ - /** - * Creates a new ContextManager. - * - * @param sessionId - * @param maxPacketSize - * @param server - * @param frontend - * @param socketKey - * @param translationScope - * @param registry - */ - public ClientSessionManager(String sessionId, int maxPacketSize, NIOServerIOThread server, - NIOServerProcessor frontend, SelectionKey socketKey, SimplTypesScope translationScope, - PARENT registry) - { - super(sessionId, maxPacketSize, server, frontend, socketKey, translationScope, registry); - } - - /** - * Prepares the internal buffer objects, which are passed in as parameters. - * - * This is a hook method, custom subclasses may wish to override it with different (or, in some - * cases, no) functionality. - * - * This implementation adds "content-length: " to the outgoingMessageHeaderBuf for performance - * purposes. Subclasses that do not use this optimization should override this method with one - * that does nothing. - */ - @Override - protected void prepareBuffers(StringBuilder outgoingMessageHeaderBuf) - { - outgoingMessageHeaderBuf.append(CONTENT_LENGTH_STRING + ":"); - } - - /** - * Clears the contents of the outgoingMessageHeaderBuffer so that it is prepared for the next - * outgoing message. - * - * This implementation leaves "content-length:" so that it can be reused for the next message. - * - * @param outgoingMessageHeaderBuf - */ - @Override - protected void clearOutgoingMessageHeaderBuffer(StringBuilder outgoingMessageHeaderBuf) - { - outgoingMessageHeaderBuf.delete(CONTENT_LENGTH_STRING_LENGTH + 1, outgoingMessageHeaderBuf - .length()); - } - - /** - * Clears the contents of the outgoingMessageBuffer so that it is empty and ready to recieve a new - * outgoing message. - * - * @param msgBufOutgoing - */ - @Override - protected void clearOutgoingMessageBuffer(StringBuilder outgoingMessageBuf) - { - outgoingMessageBuf.delete(0, outgoingMessageBuf.length()); - } - - /** - * Generates the outgoing message header. This implementation assumes that the - * outgoingMessageHeaderBuf contains "content-length: " and will add the content length, based on - * the contents of msgBufOutgoing, however, custom implementations for more specific purposes may - * be constructed. - * - * @param msgBufOutgoing - * @param outgoingMessageHeaderBuf - * @param incomingRequest - * TODO - * @param outgoingResponse - * TODO - */ - @Override - protected void createHeader(int messageSize, StringBuilder outgoingMessageHeaderBuf, - RequestMessage incomingRequest, ResponseMessage outgoingResponse, long uid) - { - outgoingMessageHeaderBuf.append(messageSize); - outgoingMessageHeaderBuf.append(HTTP_HEADER_LINE_DELIMITER); - - outgoingMessageHeaderBuf.append(UNIQUE_IDENTIFIER_STRING); - outgoingMessageHeaderBuf.append(':'); - outgoingMessageHeaderBuf.append(uid); - } - - /** - * Generates the outgoing message header (for updates). This implementation - * assumes that the outgoingMessageHeaderBuf contains "content-length: " and - * will add the content length, based on the contents of msgBufOutgoing, - * however, custom implementations for more specific purposes may be - * constructed. - * - * @param messageSize - * size of outgoing buffer - * @param outgoingMessageHeaderBuf - * buffer to put header parts in - * @param update - * update message going out - */ - @Override - protected void makeUpdateHeader(int messageSize, - StringBuilder outgoingMessageHeaderBuf, UpdateMessage update) - { - outgoingMessageHeaderBuf.append(messageSize); - } - - /** - * Translates response into an XML string and adds an HTTP-like header, then returns the result. - * - * translateResponseMessageToString(RequestMessage, ResponseMessage) may be overridden to provide - * more specific functionality; for example, for servers that use customized messages instead of - * XML. - * - * @param requestMessage - * - the current request. - * @param responseMessage - * - the ResponseMessage generated by processing requestMessage. - * @param messageBuffer - * - buffer must be passed in to this method -- it will contain the results of the - * translation and will be used by the calling method to send data back to the client. - * @return a String that constitutes a complete response message in XML with HTTP-like headers. - */ - @Override - protected void translateResponseMessageToStringBufferContents(RequestMessage requestMessage, - ResponseMessage responseMessage, StringBuilder messageBuffer) throws SIMPLTranslationException - { -// debug("serializing response to client..."); -// long currentTime = System.currentTimeMillis(); - SimplTypesScope.serialize(responseMessage, messageBuffer, StringFormat.XML); -// debug("...done ("+(System.currentTimeMillis()-currentTime)+"ms)"); - } -} +package ecologylab.oodss.distributed.server.clientsessionmanager; + +import java.nio.channels.SelectionKey; + +import ecologylab.collections.Scope; +import ecologylab.oodss.distributed.common.ServerConstants; +import ecologylab.oodss.distributed.impl.NIOServerIOThread; +import ecologylab.oodss.distributed.server.NIOServerProcessor; +import ecologylab.oodss.messages.RequestMessage; +import ecologylab.oodss.messages.ResponseMessage; +import ecologylab.oodss.messages.UpdateMessage; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * Stores information about the connection context for the client on the server. Should be extended + * for more specific implementations. Handles accumulating incoming messages and translating them + * into RequestMessage objects, as well as the ability to perform the messages' services and send + * their responses. + * + * Generally, this class can be driven by one or more threads, depending on the desired + * functionality. + * + * On a server, there will be one ContextManager for each client connection. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class ClientSessionManager extends TCPClientSessionManager implements ServerConstants +{ + /** + * Creates a new ContextManager. + * + * @param sessionId + * @param maxPacketSize + * @param server + * @param frontend + * @param socketKey + * @param translationScope + * @param registry + */ + public ClientSessionManager(String sessionId, int maxPacketSize, NIOServerIOThread server, + NIOServerProcessor frontend, SelectionKey socketKey, SimplTypesScope translationScope, + PARENT registry) + { + super(sessionId, maxPacketSize, server, frontend, socketKey, translationScope, registry); + } + + /** + * Prepares the internal buffer objects, which are passed in as parameters. + * + * This is a hook method, custom subclasses may wish to override it with different (or, in some + * cases, no) functionality. + * + * This implementation adds "content-length: " to the outgoingMessageHeaderBuf for performance + * purposes. Subclasses that do not use this optimization should override this method with one + * that does nothing. + */ + @Override + protected void prepareBuffers(StringBuilder outgoingMessageHeaderBuf) + { + outgoingMessageHeaderBuf.append(CONTENT_LENGTH_STRING + ":"); + } + + /** + * Clears the contents of the outgoingMessageHeaderBuffer so that it is prepared for the next + * outgoing message. + * + * This implementation leaves "content-length:" so that it can be reused for the next message. + * + * @param outgoingMessageHeaderBuf + */ + @Override + protected void clearOutgoingMessageHeaderBuffer(StringBuilder outgoingMessageHeaderBuf) + { + outgoingMessageHeaderBuf.delete(CONTENT_LENGTH_STRING_LENGTH + 1, outgoingMessageHeaderBuf + .length()); + } + + /** + * Clears the contents of the outgoingMessageBuffer so that it is empty and ready to recieve a new + * outgoing message. + * + * @param msgBufOutgoing + */ + @Override + protected void clearOutgoingMessageBuffer(StringBuilder outgoingMessageBuf) + { + outgoingMessageBuf.delete(0, outgoingMessageBuf.length()); + } + + /** + * Generates the outgoing message header. This implementation assumes that the + * outgoingMessageHeaderBuf contains "content-length: " and will add the content length, based on + * the contents of msgBufOutgoing, however, custom implementations for more specific purposes may + * be constructed. + * + * @param msgBufOutgoing + * @param outgoingMessageHeaderBuf + * @param incomingRequest + * TODO + * @param outgoingResponse + * TODO + */ + @Override + protected void createHeader(int messageSize, StringBuilder outgoingMessageHeaderBuf, + RequestMessage incomingRequest, ResponseMessage outgoingResponse, long uid) + { + outgoingMessageHeaderBuf.append(messageSize); + outgoingMessageHeaderBuf.append(HTTP_HEADER_LINE_DELIMITER); + + outgoingMessageHeaderBuf.append(UNIQUE_IDENTIFIER_STRING); + outgoingMessageHeaderBuf.append(':'); + outgoingMessageHeaderBuf.append(uid); + } + + /** + * Generates the outgoing message header (for updates). This implementation + * assumes that the outgoingMessageHeaderBuf contains "content-length: " and + * will add the content length, based on the contents of msgBufOutgoing, + * however, custom implementations for more specific purposes may be + * constructed. + * + * @param messageSize + * size of outgoing buffer + * @param outgoingMessageHeaderBuf + * buffer to put header parts in + * @param update + * update message going out + */ + @Override + protected void makeUpdateHeader(int messageSize, + StringBuilder outgoingMessageHeaderBuf, UpdateMessage update) + { + outgoingMessageHeaderBuf.append(messageSize); + } + + /** + * Translates response into an XML string and adds an HTTP-like header, then returns the result. + * + * translateResponseMessageToString(RequestMessage, ResponseMessage) may be overridden to provide + * more specific functionality; for example, for servers that use customized messages instead of + * XML. + * + * @param requestMessage + * - the current request. + * @param responseMessage + * - the ResponseMessage generated by processing requestMessage. + * @param messageBuffer + * - buffer must be passed in to this method -- it will contain the results of the + * translation and will be used by the calling method to send data back to the client. + * @return a String that constitutes a complete response message in XML with HTTP-like headers. + */ + @Override + protected void translateResponseMessageToStringBufferContents(RequestMessage requestMessage, + ResponseMessage responseMessage, StringBuilder messageBuffer) throws SIMPLTranslationException + { +// debug("serializing response to client..."); +// long currentTime = System.currentTimeMillis(); + SimplTypesScope.serialize(responseMessage, messageBuffer, StringFormat.XML); +// debug("...done ("+(System.currentTimeMillis()-currentTime)+"ms)"); + } +} diff --git a/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/DatagramClientSessionManager.java b/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/DatagramClientSessionManager.java index a95428cb..c56b167d 100644 --- a/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/DatagramClientSessionManager.java +++ b/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/DatagramClientSessionManager.java @@ -1,70 +1,70 @@ -/** - * - */ -package ecologylab.oodss.distributed.server.clientsessionmanager; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.nio.channels.SelectionKey; - -import ecologylab.collections.Scope; -import ecologylab.oodss.distributed.server.NIODatagramServer; -import ecologylab.oodss.messages.RequestMessage; -import ecologylab.oodss.messages.ResponseMessage; -import ecologylab.oodss.messages.UpdateMessage; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class DatagramClientSessionManager extends BaseSessionManager -{ - InetSocketAddress address; - - NIODatagramServer server; - - SelectionKey mostRecentKey; - - /** - * @param sessionId - * @param socket - * @param baseScope - */ - public DatagramClientSessionManager(String sessionId, NIODatagramServer server, - SelectionKey socket, PARENT baseScope, InetSocketAddress address) - { - super(sessionId, server, socket, baseScope); - - this.address = address; - this.server = server; - } - - /** - * Calls RequestMessage.performService(Scope) and returns the result. - * - * @param request - * - the request message to process. - */ - @Override - public ResponseMessage processRequest(RequestMessage request, InetAddress address) - { - return super.processRequest(request, address); - } - - @Override - public InetSocketAddress getAddress() - { - return address; - } - - @Override - public void sendUpdateToClient(UpdateMessage update) - { - server.sendMessage(update, mostRecentKey, (long) -1, getAddress()); - } - - public void updateKey(SelectionKey key) - { - mostRecentKey = key; - } -} +/** + * + */ +package ecologylab.oodss.distributed.server.clientsessionmanager; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.channels.SelectionKey; + +import ecologylab.collections.Scope; +import ecologylab.oodss.distributed.server.NIODatagramServer; +import ecologylab.oodss.messages.RequestMessage; +import ecologylab.oodss.messages.ResponseMessage; +import ecologylab.oodss.messages.UpdateMessage; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class DatagramClientSessionManager extends BaseSessionManager +{ + InetSocketAddress address; + + NIODatagramServer server; + + SelectionKey mostRecentKey; + + /** + * @param sessionId + * @param socket + * @param baseScope + */ + public DatagramClientSessionManager(String sessionId, NIODatagramServer server, + SelectionKey socket, PARENT baseScope, InetSocketAddress address) + { + super(sessionId, server, socket, baseScope); + + this.address = address; + this.server = server; + } + + /** + * Calls RequestMessage.performService(Scope) and returns the result. + * + * @param request + * - the request message to process. + */ + @Override + public ResponseMessage processRequest(RequestMessage request, InetAddress address) + { + return super.processRequest(request, address); + } + + @Override + public InetSocketAddress getAddress() + { + return address; + } + + @Override + public void sendUpdateToClient(UpdateMessage update) + { + server.sendMessage(update, mostRecentKey, (long) -1, getAddress()); + } + + public void updateKey(SelectionKey key) + { + mostRecentKey = key; + } +} diff --git a/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/HTTPGetClientSessionManager.java b/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/HTTPGetClientSessionManager.java index 88b98018..1937453d 100644 --- a/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/HTTPGetClientSessionManager.java +++ b/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/HTTPGetClientSessionManager.java @@ -1,89 +1,89 @@ -/** - * - */ -package ecologylab.oodss.distributed.server.clientsessionmanager; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.nio.channels.SelectionKey; - -import ecologylab.collections.Scope; -import ecologylab.oodss.distributed.impl.NIOServerIOThread; -import ecologylab.oodss.distributed.server.NIOServerProcessor; -import ecologylab.oodss.messages.HttpGetRequest; -import ecologylab.oodss.messages.RequestMessage; -import ecologylab.oodss.messages.ResponseMessage; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; - -/** - * A ContextManager for handling HTTP Get requests. Can be used to respond to browser requests. - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class HTTPGetClientSessionManager extends HTTPClientSessionManager -{ - public static final String HTTP_PREPEND = "GET /"; - - public static final int HTTP_PREPEND_LENGTH = HTTP_PREPEND.length(); - - /** - * @param token - * @param server - * @param socketKey - * @param translationScope - * @param registry - */ - public HTTPGetClientSessionManager(String token, int maxPacketSize, NIOServerIOThread server, - NIOServerProcessor frontend, SelectionKey socketKey, SimplTypesScope translationScope, - PARENT registry) - { - super(token, maxPacketSize, server, frontend, socketKey, translationScope, registry); - - this.initialized = true; - } - - /** - * This method only handles HttpGetRequest messages; it will report an error for any - * non-HttpGetRequest. Otherwise, it will not add anything to the msgBufOutgoing, as - * HttpGetRequests should only have a header and no contnents - * - * @see ecologylab.oodss.distributed.server.clientsessionmanager.ClientSessionManager#translateResponseMessageToString(ecologylab.oodss.messages.RequestMessage, - * ecologylab.oodss.messages.ResponseMessage) - */ - @Override - protected void translateResponseMessageToStringBufferContents(RequestMessage requestMessage, - ResponseMessage responseMessage, StringBuilder outgoingMessageBuf) - throws SIMPLTranslationException - { - if (!(requestMessage instanceof HttpGetRequest)) - { - debug("ERROR! HTTPGetContextManager only handles HttpGetRequests!"); - } - } - - /** - * This client manager operates primarily on HTTP header data, as it is unlikely that a GET - * request will contain an actual RequestMessage. - * - * @throws UnsupportedEncodingException - * @see ecologylab.oodss.distributed.server.clientsessionmanager.ClientSessionManager#translateStringToRequestMessage(java.lang.String) - */ - @Override - protected RequestMessage translateStringToRequestMessage(CharSequence messageSequence) - throws SIMPLTranslationException, UnsupportedEncodingException - { - String messageString = messageSequence.toString(); - - if (messageString.startsWith(HTTP_PREPEND)) - { - int endIndex = messageString.lastIndexOf(HTTP_APPEND); - messageString = messageString.substring(HTTP_PREPEND_LENGTH, endIndex); - messageString = URLDecoder.decode(messageString, "UTF-8"); - debug("fixed message! " + messageString); - } - - return super.translateStringToRequestMessage(messageString); - } -} +/** + * + */ +package ecologylab.oodss.distributed.server.clientsessionmanager; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.nio.channels.SelectionKey; + +import ecologylab.collections.Scope; +import ecologylab.oodss.distributed.impl.NIOServerIOThread; +import ecologylab.oodss.distributed.server.NIOServerProcessor; +import ecologylab.oodss.messages.HttpGetRequest; +import ecologylab.oodss.messages.RequestMessage; +import ecologylab.oodss.messages.ResponseMessage; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; + +/** + * A ContextManager for handling HTTP Get requests. Can be used to respond to browser requests. + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class HTTPGetClientSessionManager extends HTTPClientSessionManager +{ + public static final String HTTP_PREPEND = "GET /"; + + public static final int HTTP_PREPEND_LENGTH = HTTP_PREPEND.length(); + + /** + * @param token + * @param server + * @param socketKey + * @param translationScope + * @param registry + */ + public HTTPGetClientSessionManager(String token, int maxPacketSize, NIOServerIOThread server, + NIOServerProcessor frontend, SelectionKey socketKey, SimplTypesScope translationScope, + PARENT registry) + { + super(token, maxPacketSize, server, frontend, socketKey, translationScope, registry); + + this.initialized = true; + } + + /** + * This method only handles HttpGetRequest messages; it will report an error for any + * non-HttpGetRequest. Otherwise, it will not add anything to the msgBufOutgoing, as + * HttpGetRequests should only have a header and no contnents + * + * @see ecologylab.oodss.distributed.server.clientsessionmanager.ClientSessionManager#translateResponseMessageToString(ecologylab.oodss.messages.RequestMessage, + * ecologylab.oodss.messages.ResponseMessage) + */ + @Override + protected void translateResponseMessageToStringBufferContents(RequestMessage requestMessage, + ResponseMessage responseMessage, StringBuilder outgoingMessageBuf) + throws SIMPLTranslationException + { + if (!(requestMessage instanceof HttpGetRequest)) + { + debug("ERROR! HTTPGetContextManager only handles HttpGetRequests!"); + } + } + + /** + * This client manager operates primarily on HTTP header data, as it is unlikely that a GET + * request will contain an actual RequestMessage. + * + * @throws UnsupportedEncodingException + * @see ecologylab.oodss.distributed.server.clientsessionmanager.ClientSessionManager#translateStringToRequestMessage(java.lang.String) + */ + @Override + protected RequestMessage translateStringToRequestMessage(CharSequence messageSequence) + throws SIMPLTranslationException, UnsupportedEncodingException + { + String messageString = messageSequence.toString(); + + if (messageString.startsWith(HTTP_PREPEND)) + { + int endIndex = messageString.lastIndexOf(HTTP_APPEND); + messageString = messageString.substring(HTTP_PREPEND_LENGTH, endIndex); + messageString = URLDecoder.decode(messageString, "UTF-8"); + debug("fixed message! " + messageString); + } + + return super.translateStringToRequestMessage(messageString); + } +} diff --git a/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/TCPClientSessionManager.java b/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/TCPClientSessionManager.java index 554e3b83..279a5fae 100644 --- a/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/TCPClientSessionManager.java +++ b/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/TCPClientSessionManager.java @@ -1,1144 +1,1144 @@ -/** - * - */ -package ecologylab.oodss.distributed.server.clientsessionmanager; - -import java.io.UnsupportedEncodingException; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.channels.SelectionKey; -import java.nio.channels.SocketChannel; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.zip.DataFormatException; -import java.util.zip.Deflater; -import java.util.zip.Inflater; - -import ecologylab.collections.Scope; -import ecologylab.generic.StringTools; -import ecologylab.oodss.distributed.common.NetworkingConstants; -import ecologylab.oodss.distributed.common.ServerConstants; -import ecologylab.oodss.distributed.common.SessionObjects; -import ecologylab.oodss.distributed.impl.MessageWithMetadata; -import ecologylab.oodss.distributed.impl.MessageWithMetadataPool; -import ecologylab.oodss.distributed.impl.NIOServerIOThread; -import ecologylab.oodss.distributed.server.NIOServerProcessor; -import ecologylab.oodss.exceptions.BadClientException; -import ecologylab.oodss.messages.RequestMessage; -import ecologylab.oodss.messages.ResponseMessage; -import ecologylab.oodss.messages.UpdateMessage; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * The base class for all ContextManagers, objects that track the state and respond to clients on a - * server. There is a one-to-one correspondence between connected clients and ContextManager - * instances. - * - * AbstractContextManager handles all encoding and decoding of messages, as well as translating - * them. Hook methods provide places where subclasses may modify behavior for specific purposes. - * - * Typical usage is to have the context manager's request queue be filled by a network thread, while - * it is emptied by a working thread. - * - * The normal cycle for filling the queue is to call acquireIncomingSequenceBuf() to clear and get - * the incomingCharBuffer, then fill it externally (normally passing it as an argument to a - * CharsetDecoder.decode call), then calling processIncomingSequenceBufToQueue() to release it and - * let the ContextManager store the characters, converting messages into objects as they become - * available. - * - * For a complete, basic implementation (which is suitable for most uses), see - * {@link ecologylab.oodss.distributed.server.clientsessionmanager.ClientSessionManager - * ContextManager}. - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public abstract class TCPClientSessionManager extends BaseSessionManager - implements ServerConstants -{ - /** - * Stores the key-value pairings from a parsed HTTP-like header on an incoming message. - */ - protected final HashMap headerMap = new HashMap(); - - protected int startReadIndex = 0; - - /** Stores outgoing header character data. */ - protected final StringBuilder headerBufOutgoing = new StringBuilder( - MAX_HTTP_HEADER_LENGTH); - - protected final StringBuilder startLine = new StringBuilder( - MAX_HTTP_HEADER_LENGTH); - - /** - * The network communicator that will handle all the reading and writing for the socket associated - * with this ContextManager - */ - protected NIOServerIOThread server; - - /** - * The maximum message length allowed for clients that connect to this session manager. Note that - * most of the buffers used by AbstractClientManager are mutable in size, and will dynamically - * reallocate as necessary if they were initialized to be too small. - */ - protected int maxMessageSize; - - /** Used to translate incoming message XML strings into RequestMessages. */ - protected SimplTypesScope translationScope; - - /** - * stores the sequence of characters read from the header of an incoming message, may need to - * persist across read calls, as the entire header may not be sent at once. - */ - private final StringBuilder currentHeaderSequence = new StringBuilder(); - - /** - * stores the sequence of characters read from the header of an incoming message and identified as - * being a key for a header entry; may need to persist across read calls. - */ - private final StringBuilder currentKeyHeaderSequence = new StringBuilder(); - - /** - * Tracks the number of bad transmissions from the client; used for determining if a client is - * bad. - */ - private int badTransmissionCount; - - private int endOfFirstHeader = -1; - - /** - * Counts how many characters still need to be extracted from the incomingMessageBuffer before - * they can be turned into a message (based upon the HTTP header). A value of -1 means that there - * is not yet a complete header, so no length has been determined (yet). - */ - private int contentLengthRemaining = -1; - - /** - * Specifies whether or not the current message uses compression. - */ - private String contentEncoding = "identity"; - - /** - * Set of encoding schemes that the client supports - */ - private Set availableEncodings = new HashSet(); - - /** - * Stores the first XML message from the incomingMessageBuffer, or parts of it (if it is being - * read over several invocations). - */ - private StringBuilder persistentMessageBuffer = null; - - private long contentUid = -1; - - private Inflater inflater = new Inflater(); - - private Deflater deflater = new Deflater(); - - /** - * A queue of the requests to be performed by this ContextManager. Subclasses may override - * functionality and not use requestQueue. - */ - protected final Queue> requestQueue = new LinkedBlockingQueue>(); - - protected final MessageWithMetadataPool reqPool = new MessageWithMetadataPool( - 2, - 4); - - protected CharsetDecoder decoder = CHARSET - .newDecoder(); - - protected CharsetEncoder encoder = CHARSET - .newEncoder(); - - private static final String POST_PREFIX = "POST "; - - private static final String GET_PREFIX = "GET "; - - /** - * Creates a new ContextManager. - * - * @param sessionId - * @param clientSessionScope - * TODO - * @param maxMessageSizeIn - * @param server - * @param frontend - * @param socket - * @param translationScope - * @param registry - */ - public TCPClientSessionManager(String sessionId, int maxMessageSizeIn, NIOServerIOThread server, - NIOServerProcessor frontend, SelectionKey socket, SimplTypesScope translationScope, - PARENT baseScope) - { - super(sessionId, frontend, socket, baseScope); - - this.server = server; - this.translationScope = translationScope; - - // set up session id - this.sessionId = sessionId; - - this.maxMessageSize = maxMessageSizeIn; - - this.handle = new SessionHandle(this); - this.localScope.put(SessionObjects.SESSION_HANDLE, this.handle); - - this.prepareBuffers(headerBufOutgoing); - } - - /** - * Extracts messages from the given CharBuffer, using HTTP-like headers, converting them into - * RequestMessage instances, then enqueues those instances. - * - * enqueueStringMessage will normally be called repeatedly, as new data comes in from a client. It - * will automatically parse messages that are split up over multiple reads, and will handle - * multiple messages in one read, if necessary. - * - * @param message - * the CharBuffer containing one or more messages, or pieces of messages. - */ - public synchronized final void processIncomingSequenceBufToQueue(CharBuffer incomingSequenceBuf) - throws CharacterCodingException, BadClientException - { - // debug("incoming: " + incomingSequenceBuf); - - StringBuilder msgBufIncoming = this.frontend.getSharedStringBuilderPool().acquire(); - - msgBufIncoming.append(incomingSequenceBuf); - - try - { - // look for HTTP header - while (msgBufIncoming.length() > 0) - { - if (endOfFirstHeader == -1) - { - endOfFirstHeader = this.parseHeader(startReadIndex, msgBufIncoming); - } - - if (endOfFirstHeader == -1) - { /* - * no header yet; if it's too large, bad client; if it's not too large yet, just exit, - * it'll get checked again when more data comes down the pipe - */ - if (msgBufIncoming.length() > NetworkingConstants.MAX_HTTP_HEADER_LENGTH) - { - // clear the buffer - BadClientException e = new BadClientException( - ((SocketChannel) this.socketKey.channel()).socket().getInetAddress() - .getHostAddress(), "Maximum HTTP header length exceeded. Read " - + msgBufIncoming.length() + "/" + MAX_HTTP_HEADER_LENGTH); - - msgBufIncoming.setLength(0); - - throw e; - } - - // next time around, start reading from where we left off this - // time - startReadIndex = msgBufIncoming.length(); - - break; - } - else - { // we've read all of the header, and have it loaded into - // the map; - // now we can use it - if (contentLengthRemaining == -1) - { - try - { - // handle all header information here; delete it when - // done - // here - String contentLengthString = this.headerMap.get(CONTENT_LENGTH_STRING); - contentLengthRemaining = (contentLengthString != null) ? Integer - .parseInt(contentLengthString) : 0; - - String uidString = this.headerMap.get(UNIQUE_IDENTIFIER_STRING); - contentUid = (uidString != null) ? Long.parseLong(uidString) : 0; - - this.contentEncoding = this.headerMap.get(HTTP_CONTENT_CODING); - - String encodings = this.headerMap.get(HTTP_ACCEPT_ENCODING); - if (encodings != null) - { - String[] encodingList = encodings.split(","); - - for (String encoding : encodingList) - { - this.availableEncodings.add(encoding); - } - } - - // done with the header text; delete it; header values - // will - // be retained for later processing by subclasses - msgBufIncoming.delete(0, endOfFirstHeader); - } - catch (NumberFormatException e) - { - e.printStackTrace(); - contentLengthRemaining = -1; - } - // next time we read the header (the next message), we need - // to - // start from the beginning - startReadIndex = 0; - } - } - - /* - * we have the end of the header (otherwise we would have broken out earlier). If we don't - * have the content length, something bad happened, because it should have been read. - */ - if (contentLengthRemaining == -1) - { - /* - * if we still don't have the remaining length, then there was a problem - */ - break; - } - else if (contentLengthRemaining > maxMessageSize) - { - throw new BadClientException(((SocketChannel) this.socketKey.channel()).socket() - .getInetAddress().getHostAddress(), "Specified content length too large: " - + contentLengthRemaining); - } - - try - { - // see if the incoming buffer has enough characters to - // include the specified content length - if (persistentMessageBuffer == null) - { - persistentMessageBuffer = this.frontend.getSharedStringBuilderPool().acquire(); - } - if (msgBufIncoming.length() >= contentLengthRemaining) - { - persistentMessageBuffer.append(msgBufIncoming.substring(0, contentLengthRemaining)); - - msgBufIncoming.delete(0, contentLengthRemaining); - - // reset to do a new read on the next invocation - contentLengthRemaining = -1; - endOfFirstHeader = -1; - } - else - { - persistentMessageBuffer.append(msgBufIncoming); - - // indicate that we need to get more from the buffer in - // the next invocation - contentLengthRemaining -= msgBufIncoming.length(); - - msgBufIncoming.setLength(0); - } - } - catch (NullPointerException e) - { - e.printStackTrace(); - } - - if ((contentLengthRemaining == -1)) - { /* - * if we've read a complete message, then contentLengthRemaining will be reset to -1 - */ - try - { - if (this.contentEncoding == null || this.contentEncoding.equals("identity")) - { - processString(persistentMessageBuffer, contentUid); - } - else if (contentEncoding.equals(HTTP_DEFLATE_ENCODING)) - { - try - { - processString(this.unCompress(persistentMessageBuffer), contentUid); - } - catch (DataFormatException e) - { - throw new BadClientException(((SocketChannel) this.socketKey.channel()).socket() - .getInetAddress().getHostAddress(), "Content was not encoded properly: " - + e.getMessage()); - } - } - else - { - throw new BadClientException(((SocketChannel) this.socketKey.channel()).socket() - .getInetAddress().getHostAddress(), "Content encoding: " + contentEncoding - + " not supported!"); - } - } - finally - { - // clean up: clear the message buffer and the header values - this.frontend.getSharedStringBuilderPool().release(persistentMessageBuffer); - persistentMessageBuffer = null; - - this.headerMap.clear(); - StringTools.clear(this.startLine); - } - } - } - } - finally - { - this.frontend.getSharedStringBuilderPool().release(msgBufIncoming); - } - } - - private CharSequence unCompress(StringBuilder firstMessageBuffer) - throws CharacterCodingException, DataFormatException - { - CharBuffer zippingChars = this.frontend.getSharedCharBufferPool().acquire(); - ByteBuffer zippingInBytes = this.frontend.getSharedByteBufferPool().acquire(); - - zippingChars.clear(); - - firstMessageBuffer.getChars(0, firstMessageBuffer.length(), zippingChars.array(), 0); - zippingChars.position(0); - zippingChars.limit(firstMessageBuffer.length()); - - zippingInBytes.clear(); - - encoder.reset(); - encoder.encode(zippingChars, zippingInBytes, true); - encoder.flush(zippingInBytes); - - zippingInBytes.flip(); - - inflater.reset(); - inflater.setInput(zippingInBytes.array(), zippingInBytes.position(), zippingInBytes.limit()); - - ByteBuffer zippingOutBytes = this.frontend.getSharedByteBufferPool().acquire(); - - zippingOutBytes.clear(); - inflater.inflate(zippingOutBytes.array(), zippingOutBytes.position(), zippingOutBytes.limit()); - - zippingOutBytes.position(0); - zippingOutBytes.limit(inflater.getTotalOut()); - this.frontend.getSharedByteBufferPool().release(zippingInBytes); - - zippingChars.clear(); - - decoder.reset(); - decoder.decode(zippingOutBytes, zippingChars, true); - decoder.flush(zippingChars); - - this.frontend.getSharedByteBufferPool().release(zippingOutBytes); - - zippingChars.flip(); - - firstMessageBuffer.setLength(0); - - firstMessageBuffer.append(zippingChars.array(), 0, zippingChars.limit()); - - this.frontend.getSharedCharBufferPool().release(zippingChars); - - return firstMessageBuffer; - - } - - /** - * Calls processRequest(RequestMessage) on each queued message as they are acquired through - * getNextRequest() and finishing when isMessageWaiting() returns false. - * - * The functionality of processAllMessagesAndSendResponses() may be overridden by overridding the - * following methods: isMessageWaiting(), processRequest(RequestMessage), getNextRequest(). - * - * @throws BadClientException - */ - public final void processAllMessagesAndSendResponses() throws BadClientException - { - while (isMessageWaiting()) - { - this.processNextMessageAndSendResponse(); - } - } - - /** - * Sets the SelectionKey, and sets the new SelectionKey to have the same attachment (session id) - * as the old one. - * - * @param socket - * the socket to set - */ - public void setSocket(SelectionKey socket) - { - String sessionId = (String) this.socketKey.attachment(); - - this.socketKey = socket; - - this.socketKey.attach(sessionId); - } - - protected abstract void clearOutgoingMessageBuffer(StringBuilder outgoingMessageBuf); - - protected abstract void clearOutgoingMessageHeaderBuffer(StringBuilder outgoingMessageHeaderBuf); - - protected abstract void createHeader(int messageSize, StringBuilder outgoingMessageHeaderBuf, - RequestMessage incomingRequest, ResponseMessage outgoingResponse, long uid); - - protected abstract void makeUpdateHeader(int messageSize, StringBuilder headerBufOutgoing, - UpdateMessage update); - - /** - * Parses the header of an incoming set of characters (i.e. a message from a client to a server), - * loading all of the HTTP-like headers into the given headerMap. - * - * If headerMap is null, this method will throw a null pointer exception. - * - * @param allIncomingChars - * - the characters read from an incoming stream. - * @param headerMap - * - the map into which all of the parsed headers will be placed. - * @return the length of the parsed header, or -1 if it was not yet found. - */ - protected int parseHeader(int startChar, StringBuilder allIncomingChars) - { - // indicates that we might be at the end of the header - boolean maybeEndSequence = false; - - // true if the start line has been found, or if a key has been found - // instead - boolean noMoreStartLine = false; - - char currentChar; - - synchronized (currentHeaderSequence) - { - StringTools.clear(currentHeaderSequence); - StringTools.clear(currentKeyHeaderSequence); - - int length = allIncomingChars.length(); - - for (int i = 0; i < length; i++) - { - currentChar = allIncomingChars.charAt(i); - - switch (currentChar) - { - case (':'): - /* - * we have the end of a key; move the currentHeaderSequence into the - * currentKeyHeaderSequence and clear it - */ - currentKeyHeaderSequence.append(currentHeaderSequence); - - StringTools.clear(currentHeaderSequence); - - noMoreStartLine = true; - - break; - case ('\r'): - /* - * we have the end of a line; if there's a CRLF, then we have the end of the value - * sequence or the end of the header. - */ - if (allIncomingChars.charAt(i + 1) == '\n') - { - if (!maybeEndSequence) - { - if (noMoreStartLine) - { // load the key/value pair - headerMap.put(currentKeyHeaderSequence.toString().toLowerCase(), - currentHeaderSequence.toString().trim()); - } - else - { // we potentially have data w/o a key-value pair; this - // is the start-line of an HTTP header - StringTools.clear(startLine); - this.startLine.append(currentHeaderSequence); - - noMoreStartLine = true; - } - - StringTools.clear(currentKeyHeaderSequence); - StringTools.clear(currentHeaderSequence); - - i++; // so we don't re-read that last character - } - else - { // end of the header - return i + 2; - } - - maybeEndSequence = true; - } - break; - default: - currentHeaderSequence.append(currentChar); - maybeEndSequence = false; - break; - } - } - - // if we got here, we didn't finish the header - return -1; - } - } - - protected abstract void prepareBuffers(StringBuilder outgoingMessageHeaderBuf); - - protected abstract void translateResponseMessageToStringBufferContents( - RequestMessage requestMessage, ResponseMessage responseMessage, StringBuilder messageBuffer) - throws SIMPLTranslationException; - - /** - * Translates the given XML String into a RequestMessage object. - * - * translateStringToRequestMessage(String) may be overridden to provide specific functionality, - * such as a ContextManager that does not use XML Strings. - * - * @param messageCharSequence - * - an XML String representing a RequestMessage object. - * @return the RequestMessage created by translating messageString into an object. - * @throws SIMPLTranslationException - * if an error occurs when translating from XML into a RequestMessage. - * @throws UnsupportedEncodingException - * if the String is not encoded properly. - */ - protected RequestMessage translateStringToRequestMessage(CharSequence messageCharSequence) - throws SIMPLTranslationException, UnsupportedEncodingException - { - String startLineString = null; - - // debug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); - // debug(this.startLine); - - if (this.startLine == null || (startLineString = startLine.toString()).equals("")) - { // normal case - return translateOODSSRequest(messageCharSequence, startLineString); - } - else if (startLineString.startsWith(GET_PREFIX)) - { // get case - // debug("GET case!"); - return this.translateGetRequest(messageCharSequence, startLineString); - } - else if (startLineString.startsWith(POST_PREFIX)) - { // post case - return translatePostRequest(messageCharSequence, startLineString); - } - else - { // made of fail case - return translateOtherRequest(messageCharSequence, startLineString); - } - } - - /** - * Translates an incoming character sequence identified to be an OODSS request message (not a GET - * or POST request). - * - * @param messageCharSequence - * @param startLineString - * TODO - * @return The request message contained in the message. - * @throws SIMPLTranslationException - */ - protected RequestMessage translateOODSSRequest(CharSequence messageCharSequence, - String startLineString) throws SIMPLTranslationException - { - return (RequestMessage) translationScope.deserialize(messageCharSequence, StringFormat.XML); - } - - /** - * Translates an incoming character sequence identified to be a GET request. - * - * This implementation returns null. - * - * @param messageCharSequence - * @param startLineString - * TODO - * @return null. - */ - protected RequestMessage translateGetRequest(CharSequence messageCharSequence, - String startLineString) throws SIMPLTranslationException - { - return null; - } - - /** - * Translates an incoming character sequence identified to be a POST request. - * - * This implementation expects the POST request to contain a nested OODSS request. - * - * @param messageCharSequence - * @param startLineString - * TODO - * @return - * @throws SIMPLTranslationException - */ - protected RequestMessage translatePostRequest(CharSequence messageCharSequence, - String startLineString) throws SIMPLTranslationException - { - String messageString = messageCharSequence.toString(); - - if (!messageString.startsWith("<")) - messageString = messageString.substring(messageString.indexOf('=') + 1); - - return this.translateOODSSRequest(messageString, startLineString); - } - - /** - * Translates an incoming character sequence that cannot be identified. Called when the first line - * of the request is not empty, not GET, and not POST. - * - * This implementation returns null. - * - * @param startLineString - * TODO - * - * @return null. - */ - protected RequestMessage translateOtherRequest(CharSequence messageCharSequence, - String startLineString) throws SIMPLTranslationException - { - return null; - } - - /** - * Adds the given request to this's request queue. - * - * enqueueRequest(RequestMessage) is a hook method for ContextManagers that need to implement - * other functionality, such as prioritizing messages. - * - * If enqueueRequest(RequestMessage) is overridden, the following methods should also be - * overridden: isMessageWaiting(), getNextRequest(). - * - * @param request - */ - protected void enqueueRequest(MessageWithMetadata request) - { - messageWaiting = this.requestQueue.offer(request); - } - - /** - * Returns the next message in the request queue. - * - * getNextRequest() may be overridden to provide specific functionality, such as a priority queue. - * In this case, it is important to override the following methods: isMessageWaiting(), - * enqueueRequest(). - * - * @return the next message in the requestQueue. - */ - protected MessageWithMetadata getNextRequest() - { - synchronized (requestQueue) - { - int queueSize = requestQueue.size(); - - if (queueSize == 1) - { - messageWaiting = false; - } - - // return null if none left, or the next Request otherwise - return requestQueue.poll(); - } - } - - /** - * Calls processRequest(RequestMessage) on the result of getNextRequest(). - * - * In order to override functionality processRequest(RequestMessage) and/or getNextRequest() - * should be overridden. - * - */ - private final void processNextMessageAndSendResponse() - { - this.processRequest(this.getNextRequest()); - } - - /** - * Calls performService(requestMessage), then converts the resulting ResponseMessage into a - * String, adds the HTTP-like headers, and passes the completed String to the server backend for - * sending to the client. - * - * @param request - * - the request message to process. - */ - protected final ResponseMessage processRequest( - MessageWithMetadata requestWithMetadata) - { - RequestMessage request = requestWithMetadata.getMessage(); - - ResponseMessage response = super.processRequest(request, ((SocketChannel) this.socketKey - .channel()).socket().getInetAddress()); - - if (response != null) - { // if the response is null, then we do - // nothing else - sendResponseToClient(requestWithMetadata, response, request); - } - else - { - debug("context manager did not produce a response message."); - } - - requestWithMetadata = reqPool.release(requestWithMetadata); - - return response; - } - - private synchronized void sendResponseToClient( - MessageWithMetadata requestWithMetadata, ResponseMessage response, - RequestMessage request) - { - - StringBuilder msgBufOutgoing = this.frontend.getSharedStringBuilderPool().acquire(); - - try - { - // setup outgoingMessageBuffer - this.translateResponseMessageToStringBufferContents(request, response, msgBufOutgoing); - } - catch (SIMPLTranslationException e1) - { - e1.printStackTrace(); - } - - try - { - ByteBuffer compressedMessageBuffer = null; - CharBuffer outgoingChars = this.frontend.getSharedCharBufferPool().acquire(); - - boolean usingCompression = this.availableEncodings.contains(HTTP_DEFLATE_ENCODING); - /* - * If Compressing must know the length of the data being sent so must compress here - */ - if (usingCompression) - { - compressedMessageBuffer = this.frontend.getSharedByteBufferPool().acquire(); - compressedMessageBuffer.clear(); - this.compress(msgBufOutgoing, compressedMessageBuffer); - compressedMessageBuffer.flip(); - this.clearOutgoingMessageBuffer(msgBufOutgoing); - } - - this.clearOutgoingMessageHeaderBuffer(headerBufOutgoing); - - // setup outgoingMessageHeaderBuffer - this.createHeader((usingCompression) ? compressedMessageBuffer.limit() : msgBufOutgoing - .length(), headerBufOutgoing, request, response, requestWithMetadata.getUid()); - - if (usingCompression) - { - headerBufOutgoing.append(HTTP_HEADER_LINE_DELIMITER); - headerBufOutgoing.append(HTTP_CONTENT_CODING); - headerBufOutgoing.append(":"); - headerBufOutgoing.append(HTTP_DEFLATE_ENCODING); - } - - headerBufOutgoing.append(HTTP_HEADER_TERMINATOR); - - // move the characters from the outgoing buffers into - // outgoingChars using bulk get and put methods - outgoingChars.clear(); - - headerBufOutgoing.getChars(0, headerBufOutgoing.length(), outgoingChars.array(), 0); - - if (!usingCompression) - { - // assert that the size of the message is smaller than the buffer. - // if not, increase the buffer. - if (msgBufOutgoing.length() + headerBufOutgoing.length() > outgoingChars.capacity()) - { - int newCapacity = outgoingChars.capacity()*2; - this.frontend.increaseSharedBufferPoolSize(newCapacity); - outgoingChars = this.frontend.getSharedCharBufferPool().acquire(); - } - - msgBufOutgoing.getChars(0, msgBufOutgoing.length(), outgoingChars.array(), - headerBufOutgoing.length()); - - outgoingChars.limit(headerBufOutgoing.length() + msgBufOutgoing.length()); - - this.clearOutgoingMessageBuffer(msgBufOutgoing); - } - else - { - outgoingChars.limit(headerBufOutgoing.length()); - } - - outgoingChars.position(0); - - ByteBuffer outgoingBuffer = this.server.acquireByteBufferFromPool(); - - synchronized (encoder) - { - encoder.reset(); - - encoder.encode(outgoingChars, outgoingBuffer, true); - - encoder.flush(outgoingBuffer); - } - - this.frontend.getSharedCharBufferPool().release(outgoingChars); - - if (usingCompression) - { - outgoingBuffer.put(compressedMessageBuffer); - this.frontend.getSharedByteBufferPool().release(compressedMessageBuffer); - } - - server.enqueueBytesForWriting(this.socketKey, outgoingBuffer); - } - catch (DataFormatException e) - { - debug("Failed to compress response!"); - e.printStackTrace(); - } - finally - { - this.frontend.getSharedStringBuilderPool().release(msgBufOutgoing); - } - - // debug("...done ("+(System.currentTimeMillis()-currentTime)+"ms)"); - } - - @Override - public synchronized void sendUpdateToClient(UpdateMessage update) - { - StringBuilder msgBufOutgoing = this.frontend.getSharedStringBuilderPool().acquire(); - - if (this.isInvalidating()) - { - return; - } - try - { - // setup outgoingMessageBuffer - SimplTypesScope.serialize(update, msgBufOutgoing, StringFormat.XML); - } - catch (SIMPLTranslationException e1) - { - e1.printStackTrace(); - } - - try - { - ByteBuffer compressedMessageBuffer = null; - CharBuffer outgoingChars = this.frontend.getSharedCharBufferPool().acquire(); - - boolean usingCompression = this.availableEncodings.contains(HTTP_DEFLATE_ENCODING); - /* - * If Compressing must know the length of the data being sent so must compress here - */ - if (usingCompression) - { - compressedMessageBuffer = this.frontend.getSharedByteBufferPool().acquire(); - - compressedMessageBuffer.clear(); - this.compress(msgBufOutgoing, compressedMessageBuffer); - compressedMessageBuffer.flip(); - this.clearOutgoingMessageBuffer(msgBufOutgoing); - } - - this.clearOutgoingMessageHeaderBuffer(headerBufOutgoing); - - // setup outgoingMessageHeaderBuffer - this.makeUpdateHeader((usingCompression) ? compressedMessageBuffer.limit() : msgBufOutgoing - .length(), headerBufOutgoing, update); - - if (usingCompression) - { - headerBufOutgoing.append(HTTP_HEADER_LINE_DELIMITER); - headerBufOutgoing.append(HTTP_CONTENT_CODING); - headerBufOutgoing.append(":"); - headerBufOutgoing.append(HTTP_DEFLATE_ENCODING); - } - - headerBufOutgoing.append(HTTP_HEADER_TERMINATOR); - - // move the characters from the outgoing buffers into - // outgoingChars using bulk get and put methods - outgoingChars.clear(); - - headerBufOutgoing.getChars(0, headerBufOutgoing.length(), outgoingChars.array(), 0); - - if (!usingCompression) - { - msgBufOutgoing.getChars(0, msgBufOutgoing.length(), outgoingChars.array(), - headerBufOutgoing.length()); - - outgoingChars.limit(headerBufOutgoing.length() + msgBufOutgoing.length()); - - this.clearOutgoingMessageBuffer(msgBufOutgoing); - } - else - { - outgoingChars.limit(headerBufOutgoing.length()); - } - - outgoingChars.position(0); - - ByteBuffer outgoingBuffer = this.server.acquireByteBufferFromPool(); - - synchronized (encoder) - { - encoder.reset(); - - encoder.encode(outgoingChars, outgoingBuffer, true); - - encoder.flush(outgoingBuffer); - } - - this.frontend.getSharedCharBufferPool().release(outgoingChars); - - if (usingCompression) - { - outgoingBuffer.put(compressedMessageBuffer); - this.frontend.getSharedByteBufferPool().release(compressedMessageBuffer); - } - - server.enqueueBytesForWriting(this.socketKey, outgoingBuffer); - } - catch (DataFormatException e) - { - debug("Failed to compress update!"); - e.printStackTrace(); - } - finally - { - this.frontend.getSharedStringBuilderPool().release(msgBufOutgoing); - } - } - - private void compress(StringBuilder src, ByteBuffer dest) throws DataFormatException - { - CharBuffer zippingChars = this.frontend.getSharedCharBufferPool().acquire(); - zippingChars.clear(); - - src.getChars(0, src.length(), zippingChars.array(), 0); - zippingChars.position(0); - zippingChars.limit(src.length()); - - ByteBuffer zippingInBytes = this.frontend.getSharedByteBufferPool().acquire(); - zippingInBytes.clear(); - - encoder.reset(); - encoder.encode(zippingChars, zippingInBytes, true); - encoder.flush(zippingInBytes); - - this.frontend.getSharedCharBufferPool().release(zippingChars); - - zippingInBytes.flip(); - - deflater.reset(); - deflater.setInput(zippingInBytes.array(), zippingInBytes.position(), zippingInBytes.limit()); - deflater.finish(); - - this.frontend.getSharedByteBufferPool().release(zippingInBytes); - - dest.position(dest.position() - + deflater.deflate(dest.array(), dest.position(), dest.remaining())); - - } - - /** - * Takes an incoming message in the form of an XML String and converts it into a RequestMessage - * using translateStringToRequestMessage(String). Then places the RequestMessage on the - * requestQueue using enqueueRequest(). - * - * @param incomingMessage - * @param headerMap2 - * @throws BadClientException - */ - private final void processString(CharSequence incomingMessage, long incomingUid) - throws BadClientException - { - Exception failReason = null; - RequestMessage request = null; - try - { - request = this.translateStringToRequestMessage(incomingMessage); - } - catch (SIMPLTranslationException e) - { - // drop down to request == null, below - failReason = e; - } - catch (UnsupportedEncodingException e) - { - // drop down to request == null, below - failReason = e; - } - - if (request == null) - { - if (incomingMessage.length() > 100) - { - debug("ERROR; incoming message could not be translated: " + incomingMessage.toString()); - - debug("HEADERS:"); - debug(headerMap.toString()); - - if (failReason != null) - { - debug("EXCEPTION: " + failReason.getMessage()); - failReason.printStackTrace(); - } - } - else - { - debug("ERROR; incoming message could not be translated: " + incomingMessage.toString()); - - debug("HEADERS:"); - debug(headerMap.toString()); - - if (failReason != null) - { - debug("EXCEPTION: " + failReason.getMessage()); - failReason.printStackTrace(); - } - } - if (++badTransmissionCount >= MAXIMUM_TRANSMISSION_ERRORS) - { - throw new BadClientException(((SocketChannel) this.socketKey.channel()).socket() - .getInetAddress().getHostAddress(), "Too many Bad Transmissions: " - + badTransmissionCount); - } - // else - error("translation failed: badTransmissionCount=" + badTransmissionCount); - } - else - { - badTransmissionCount = 0; - - MessageWithMetadata pReq = this.reqPool.acquire(); - - pReq.setMessage(request); - pReq.setUid(incomingUid); - - synchronized (requestQueue) - { - this.enqueueRequest(pReq); - } - } - } - - @Override - public InetSocketAddress getAddress() - { - return (InetSocketAddress) ((SocketChannel) getSocketKey().channel()).socket() - .getRemoteSocketAddress(); - - } - - public SessionHandle getHandle() - { - return handle; - } +/** + * + */ +package ecologylab.oodss.distributed.server.clientsessionmanager; + +import java.io.UnsupportedEncodingException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.SocketChannel; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.zip.DataFormatException; +import java.util.zip.Deflater; +import java.util.zip.Inflater; + +import ecologylab.collections.Scope; +import ecologylab.generic.StringTools; +import ecologylab.oodss.distributed.common.NetworkingConstants; +import ecologylab.oodss.distributed.common.ServerConstants; +import ecologylab.oodss.distributed.common.SessionObjects; +import ecologylab.oodss.distributed.impl.MessageWithMetadata; +import ecologylab.oodss.distributed.impl.MessageWithMetadataPool; +import ecologylab.oodss.distributed.impl.NIOServerIOThread; +import ecologylab.oodss.distributed.server.NIOServerProcessor; +import ecologylab.oodss.exceptions.BadClientException; +import ecologylab.oodss.messages.RequestMessage; +import ecologylab.oodss.messages.ResponseMessage; +import ecologylab.oodss.messages.UpdateMessage; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * The base class for all ContextManagers, objects that track the state and respond to clients on a + * server. There is a one-to-one correspondence between connected clients and ContextManager + * instances. + * + * AbstractContextManager handles all encoding and decoding of messages, as well as translating + * them. Hook methods provide places where subclasses may modify behavior for specific purposes. + * + * Typical usage is to have the context manager's request queue be filled by a network thread, while + * it is emptied by a working thread. + * + * The normal cycle for filling the queue is to call acquireIncomingSequenceBuf() to clear and get + * the incomingCharBuffer, then fill it externally (normally passing it as an argument to a + * CharsetDecoder.decode call), then calling processIncomingSequenceBufToQueue() to release it and + * let the ContextManager store the characters, converting messages into objects as they become + * available. + * + * For a complete, basic implementation (which is suitable for most uses), see + * {@link ecologylab.oodss.distributed.server.clientsessionmanager.ClientSessionManager + * ContextManager}. + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public abstract class TCPClientSessionManager extends BaseSessionManager + implements ServerConstants +{ + /** + * Stores the key-value pairings from a parsed HTTP-like header on an incoming message. + */ + protected final HashMap headerMap = new HashMap(); + + protected int startReadIndex = 0; + + /** Stores outgoing header character data. */ + protected final StringBuilder headerBufOutgoing = new StringBuilder( + MAX_HTTP_HEADER_LENGTH); + + protected final StringBuilder startLine = new StringBuilder( + MAX_HTTP_HEADER_LENGTH); + + /** + * The network communicator that will handle all the reading and writing for the socket associated + * with this ContextManager + */ + protected NIOServerIOThread server; + + /** + * The maximum message length allowed for clients that connect to this session manager. Note that + * most of the buffers used by AbstractClientManager are mutable in size, and will dynamically + * reallocate as necessary if they were initialized to be too small. + */ + protected int maxMessageSize; + + /** Used to translate incoming message XML strings into RequestMessages. */ + protected SimplTypesScope translationScope; + + /** + * stores the sequence of characters read from the header of an incoming message, may need to + * persist across read calls, as the entire header may not be sent at once. + */ + private final StringBuilder currentHeaderSequence = new StringBuilder(); + + /** + * stores the sequence of characters read from the header of an incoming message and identified as + * being a key for a header entry; may need to persist across read calls. + */ + private final StringBuilder currentKeyHeaderSequence = new StringBuilder(); + + /** + * Tracks the number of bad transmissions from the client; used for determining if a client is + * bad. + */ + private int badTransmissionCount; + + private int endOfFirstHeader = -1; + + /** + * Counts how many characters still need to be extracted from the incomingMessageBuffer before + * they can be turned into a message (based upon the HTTP header). A value of -1 means that there + * is not yet a complete header, so no length has been determined (yet). + */ + private int contentLengthRemaining = -1; + + /** + * Specifies whether or not the current message uses compression. + */ + private String contentEncoding = "identity"; + + /** + * Set of encoding schemes that the client supports + */ + private Set availableEncodings = new HashSet(); + + /** + * Stores the first XML message from the incomingMessageBuffer, or parts of it (if it is being + * read over several invocations). + */ + private StringBuilder persistentMessageBuffer = null; + + private long contentUid = -1; + + private Inflater inflater = new Inflater(); + + private Deflater deflater = new Deflater(); + + /** + * A queue of the requests to be performed by this ContextManager. Subclasses may override + * functionality and not use requestQueue. + */ + protected final Queue> requestQueue = new LinkedBlockingQueue>(); + + protected final MessageWithMetadataPool reqPool = new MessageWithMetadataPool( + 2, + 4); + + protected CharsetDecoder decoder = CHARSET + .newDecoder(); + + protected CharsetEncoder encoder = CHARSET + .newEncoder(); + + private static final String POST_PREFIX = "POST "; + + private static final String GET_PREFIX = "GET "; + + /** + * Creates a new ContextManager. + * + * @param sessionId + * @param clientSessionScope + * TODO + * @param maxMessageSizeIn + * @param server + * @param frontend + * @param socket + * @param translationScope + * @param registry + */ + public TCPClientSessionManager(String sessionId, int maxMessageSizeIn, NIOServerIOThread server, + NIOServerProcessor frontend, SelectionKey socket, SimplTypesScope translationScope, + PARENT baseScope) + { + super(sessionId, frontend, socket, baseScope); + + this.server = server; + this.translationScope = translationScope; + + // set up session id + this.sessionId = sessionId; + + this.maxMessageSize = maxMessageSizeIn; + + this.handle = new SessionHandle(this); + this.localScope.put(SessionObjects.SESSION_HANDLE, this.handle); + + this.prepareBuffers(headerBufOutgoing); + } + + /** + * Extracts messages from the given CharBuffer, using HTTP-like headers, converting them into + * RequestMessage instances, then enqueues those instances. + * + * enqueueStringMessage will normally be called repeatedly, as new data comes in from a client. It + * will automatically parse messages that are split up over multiple reads, and will handle + * multiple messages in one read, if necessary. + * + * @param message + * the CharBuffer containing one or more messages, or pieces of messages. + */ + public synchronized final void processIncomingSequenceBufToQueue(CharBuffer incomingSequenceBuf) + throws CharacterCodingException, BadClientException + { + // debug("incoming: " + incomingSequenceBuf); + + StringBuilder msgBufIncoming = this.frontend.getSharedStringBuilderPool().acquire(); + + msgBufIncoming.append(incomingSequenceBuf); + + try + { + // look for HTTP header + while (msgBufIncoming.length() > 0) + { + if (endOfFirstHeader == -1) + { + endOfFirstHeader = this.parseHeader(startReadIndex, msgBufIncoming); + } + + if (endOfFirstHeader == -1) + { /* + * no header yet; if it's too large, bad client; if it's not too large yet, just exit, + * it'll get checked again when more data comes down the pipe + */ + if (msgBufIncoming.length() > NetworkingConstants.MAX_HTTP_HEADER_LENGTH) + { + // clear the buffer + BadClientException e = new BadClientException( + ((SocketChannel) this.socketKey.channel()).socket().getInetAddress() + .getHostAddress(), "Maximum HTTP header length exceeded. Read " + + msgBufIncoming.length() + "/" + MAX_HTTP_HEADER_LENGTH); + + msgBufIncoming.setLength(0); + + throw e; + } + + // next time around, start reading from where we left off this + // time + startReadIndex = msgBufIncoming.length(); + + break; + } + else + { // we've read all of the header, and have it loaded into + // the map; + // now we can use it + if (contentLengthRemaining == -1) + { + try + { + // handle all header information here; delete it when + // done + // here + String contentLengthString = this.headerMap.get(CONTENT_LENGTH_STRING); + contentLengthRemaining = (contentLengthString != null) ? Integer + .parseInt(contentLengthString) : 0; + + String uidString = this.headerMap.get(UNIQUE_IDENTIFIER_STRING); + contentUid = (uidString != null) ? Long.parseLong(uidString) : 0; + + this.contentEncoding = this.headerMap.get(HTTP_CONTENT_CODING); + + String encodings = this.headerMap.get(HTTP_ACCEPT_ENCODING); + if (encodings != null) + { + String[] encodingList = encodings.split(","); + + for (String encoding : encodingList) + { + this.availableEncodings.add(encoding); + } + } + + // done with the header text; delete it; header values + // will + // be retained for later processing by subclasses + msgBufIncoming.delete(0, endOfFirstHeader); + } + catch (NumberFormatException e) + { + e.printStackTrace(); + contentLengthRemaining = -1; + } + // next time we read the header (the next message), we need + // to + // start from the beginning + startReadIndex = 0; + } + } + + /* + * we have the end of the header (otherwise we would have broken out earlier). If we don't + * have the content length, something bad happened, because it should have been read. + */ + if (contentLengthRemaining == -1) + { + /* + * if we still don't have the remaining length, then there was a problem + */ + break; + } + else if (contentLengthRemaining > maxMessageSize) + { + throw new BadClientException(((SocketChannel) this.socketKey.channel()).socket() + .getInetAddress().getHostAddress(), "Specified content length too large: " + + contentLengthRemaining); + } + + try + { + // see if the incoming buffer has enough characters to + // include the specified content length + if (persistentMessageBuffer == null) + { + persistentMessageBuffer = this.frontend.getSharedStringBuilderPool().acquire(); + } + if (msgBufIncoming.length() >= contentLengthRemaining) + { + persistentMessageBuffer.append(msgBufIncoming.substring(0, contentLengthRemaining)); + + msgBufIncoming.delete(0, contentLengthRemaining); + + // reset to do a new read on the next invocation + contentLengthRemaining = -1; + endOfFirstHeader = -1; + } + else + { + persistentMessageBuffer.append(msgBufIncoming); + + // indicate that we need to get more from the buffer in + // the next invocation + contentLengthRemaining -= msgBufIncoming.length(); + + msgBufIncoming.setLength(0); + } + } + catch (NullPointerException e) + { + e.printStackTrace(); + } + + if ((contentLengthRemaining == -1)) + { /* + * if we've read a complete message, then contentLengthRemaining will be reset to -1 + */ + try + { + if (this.contentEncoding == null || this.contentEncoding.equals("identity")) + { + processString(persistentMessageBuffer, contentUid); + } + else if (contentEncoding.equals(HTTP_DEFLATE_ENCODING)) + { + try + { + processString(this.unCompress(persistentMessageBuffer), contentUid); + } + catch (DataFormatException e) + { + throw new BadClientException(((SocketChannel) this.socketKey.channel()).socket() + .getInetAddress().getHostAddress(), "Content was not encoded properly: " + + e.getMessage()); + } + } + else + { + throw new BadClientException(((SocketChannel) this.socketKey.channel()).socket() + .getInetAddress().getHostAddress(), "Content encoding: " + contentEncoding + + " not supported!"); + } + } + finally + { + // clean up: clear the message buffer and the header values + this.frontend.getSharedStringBuilderPool().release(persistentMessageBuffer); + persistentMessageBuffer = null; + + this.headerMap.clear(); + StringTools.clear(this.startLine); + } + } + } + } + finally + { + this.frontend.getSharedStringBuilderPool().release(msgBufIncoming); + } + } + + private CharSequence unCompress(StringBuilder firstMessageBuffer) + throws CharacterCodingException, DataFormatException + { + CharBuffer zippingChars = this.frontend.getSharedCharBufferPool().acquire(); + ByteBuffer zippingInBytes = this.frontend.getSharedByteBufferPool().acquire(); + + zippingChars.clear(); + + firstMessageBuffer.getChars(0, firstMessageBuffer.length(), zippingChars.array(), 0); + zippingChars.position(0); + zippingChars.limit(firstMessageBuffer.length()); + + zippingInBytes.clear(); + + encoder.reset(); + encoder.encode(zippingChars, zippingInBytes, true); + encoder.flush(zippingInBytes); + + zippingInBytes.flip(); + + inflater.reset(); + inflater.setInput(zippingInBytes.array(), zippingInBytes.position(), zippingInBytes.limit()); + + ByteBuffer zippingOutBytes = this.frontend.getSharedByteBufferPool().acquire(); + + zippingOutBytes.clear(); + inflater.inflate(zippingOutBytes.array(), zippingOutBytes.position(), zippingOutBytes.limit()); + + zippingOutBytes.position(0); + zippingOutBytes.limit(inflater.getTotalOut()); + this.frontend.getSharedByteBufferPool().release(zippingInBytes); + + zippingChars.clear(); + + decoder.reset(); + decoder.decode(zippingOutBytes, zippingChars, true); + decoder.flush(zippingChars); + + this.frontend.getSharedByteBufferPool().release(zippingOutBytes); + + zippingChars.flip(); + + firstMessageBuffer.setLength(0); + + firstMessageBuffer.append(zippingChars.array(), 0, zippingChars.limit()); + + this.frontend.getSharedCharBufferPool().release(zippingChars); + + return firstMessageBuffer; + + } + + /** + * Calls processRequest(RequestMessage) on each queued message as they are acquired through + * getNextRequest() and finishing when isMessageWaiting() returns false. + * + * The functionality of processAllMessagesAndSendResponses() may be overridden by overridding the + * following methods: isMessageWaiting(), processRequest(RequestMessage), getNextRequest(). + * + * @throws BadClientException + */ + public final void processAllMessagesAndSendResponses() throws BadClientException + { + while (isMessageWaiting()) + { + this.processNextMessageAndSendResponse(); + } + } + + /** + * Sets the SelectionKey, and sets the new SelectionKey to have the same attachment (session id) + * as the old one. + * + * @param socket + * the socket to set + */ + public void setSocket(SelectionKey socket) + { + String sessionId = (String) this.socketKey.attachment(); + + this.socketKey = socket; + + this.socketKey.attach(sessionId); + } + + protected abstract void clearOutgoingMessageBuffer(StringBuilder outgoingMessageBuf); + + protected abstract void clearOutgoingMessageHeaderBuffer(StringBuilder outgoingMessageHeaderBuf); + + protected abstract void createHeader(int messageSize, StringBuilder outgoingMessageHeaderBuf, + RequestMessage incomingRequest, ResponseMessage outgoingResponse, long uid); + + protected abstract void makeUpdateHeader(int messageSize, StringBuilder headerBufOutgoing, + UpdateMessage update); + + /** + * Parses the header of an incoming set of characters (i.e. a message from a client to a server), + * loading all of the HTTP-like headers into the given headerMap. + * + * If headerMap is null, this method will throw a null pointer exception. + * + * @param allIncomingChars + * - the characters read from an incoming stream. + * @param headerMap + * - the map into which all of the parsed headers will be placed. + * @return the length of the parsed header, or -1 if it was not yet found. + */ + protected int parseHeader(int startChar, StringBuilder allIncomingChars) + { + // indicates that we might be at the end of the header + boolean maybeEndSequence = false; + + // true if the start line has been found, or if a key has been found + // instead + boolean noMoreStartLine = false; + + char currentChar; + + synchronized (currentHeaderSequence) + { + StringTools.clear(currentHeaderSequence); + StringTools.clear(currentKeyHeaderSequence); + + int length = allIncomingChars.length(); + + for (int i = 0; i < length; i++) + { + currentChar = allIncomingChars.charAt(i); + + switch (currentChar) + { + case (':'): + /* + * we have the end of a key; move the currentHeaderSequence into the + * currentKeyHeaderSequence and clear it + */ + currentKeyHeaderSequence.append(currentHeaderSequence); + + StringTools.clear(currentHeaderSequence); + + noMoreStartLine = true; + + break; + case ('\r'): + /* + * we have the end of a line; if there's a CRLF, then we have the end of the value + * sequence or the end of the header. + */ + if (allIncomingChars.charAt(i + 1) == '\n') + { + if (!maybeEndSequence) + { + if (noMoreStartLine) + { // load the key/value pair + headerMap.put(currentKeyHeaderSequence.toString().toLowerCase(), + currentHeaderSequence.toString().trim()); + } + else + { // we potentially have data w/o a key-value pair; this + // is the start-line of an HTTP header + StringTools.clear(startLine); + this.startLine.append(currentHeaderSequence); + + noMoreStartLine = true; + } + + StringTools.clear(currentKeyHeaderSequence); + StringTools.clear(currentHeaderSequence); + + i++; // so we don't re-read that last character + } + else + { // end of the header + return i + 2; + } + + maybeEndSequence = true; + } + break; + default: + currentHeaderSequence.append(currentChar); + maybeEndSequence = false; + break; + } + } + + // if we got here, we didn't finish the header + return -1; + } + } + + protected abstract void prepareBuffers(StringBuilder outgoingMessageHeaderBuf); + + protected abstract void translateResponseMessageToStringBufferContents( + RequestMessage requestMessage, ResponseMessage responseMessage, StringBuilder messageBuffer) + throws SIMPLTranslationException; + + /** + * Translates the given XML String into a RequestMessage object. + * + * translateStringToRequestMessage(String) may be overridden to provide specific functionality, + * such as a ContextManager that does not use XML Strings. + * + * @param messageCharSequence + * - an XML String representing a RequestMessage object. + * @return the RequestMessage created by translating messageString into an object. + * @throws SIMPLTranslationException + * if an error occurs when translating from XML into a RequestMessage. + * @throws UnsupportedEncodingException + * if the String is not encoded properly. + */ + protected RequestMessage translateStringToRequestMessage(CharSequence messageCharSequence) + throws SIMPLTranslationException, UnsupportedEncodingException + { + String startLineString = null; + + // debug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + // debug(this.startLine); + + if (this.startLine == null || (startLineString = startLine.toString()).equals("")) + { // normal case + return translateOODSSRequest(messageCharSequence, startLineString); + } + else if (startLineString.startsWith(GET_PREFIX)) + { // get case + // debug("GET case!"); + return this.translateGetRequest(messageCharSequence, startLineString); + } + else if (startLineString.startsWith(POST_PREFIX)) + { // post case + return translatePostRequest(messageCharSequence, startLineString); + } + else + { // made of fail case + return translateOtherRequest(messageCharSequence, startLineString); + } + } + + /** + * Translates an incoming character sequence identified to be an OODSS request message (not a GET + * or POST request). + * + * @param messageCharSequence + * @param startLineString + * TODO + * @return The request message contained in the message. + * @throws SIMPLTranslationException + */ + protected RequestMessage translateOODSSRequest(CharSequence messageCharSequence, + String startLineString) throws SIMPLTranslationException + { + return (RequestMessage) translationScope.deserialize(messageCharSequence, StringFormat.XML); + } + + /** + * Translates an incoming character sequence identified to be a GET request. + * + * This implementation returns null. + * + * @param messageCharSequence + * @param startLineString + * TODO + * @return null. + */ + protected RequestMessage translateGetRequest(CharSequence messageCharSequence, + String startLineString) throws SIMPLTranslationException + { + return null; + } + + /** + * Translates an incoming character sequence identified to be a POST request. + * + * This implementation expects the POST request to contain a nested OODSS request. + * + * @param messageCharSequence + * @param startLineString + * TODO + * @return + * @throws SIMPLTranslationException + */ + protected RequestMessage translatePostRequest(CharSequence messageCharSequence, + String startLineString) throws SIMPLTranslationException + { + String messageString = messageCharSequence.toString(); + + if (!messageString.startsWith("<")) + messageString = messageString.substring(messageString.indexOf('=') + 1); + + return this.translateOODSSRequest(messageString, startLineString); + } + + /** + * Translates an incoming character sequence that cannot be identified. Called when the first line + * of the request is not empty, not GET, and not POST. + * + * This implementation returns null. + * + * @param startLineString + * TODO + * + * @return null. + */ + protected RequestMessage translateOtherRequest(CharSequence messageCharSequence, + String startLineString) throws SIMPLTranslationException + { + return null; + } + + /** + * Adds the given request to this's request queue. + * + * enqueueRequest(RequestMessage) is a hook method for ContextManagers that need to implement + * other functionality, such as prioritizing messages. + * + * If enqueueRequest(RequestMessage) is overridden, the following methods should also be + * overridden: isMessageWaiting(), getNextRequest(). + * + * @param request + */ + protected void enqueueRequest(MessageWithMetadata request) + { + messageWaiting = this.requestQueue.offer(request); + } + + /** + * Returns the next message in the request queue. + * + * getNextRequest() may be overridden to provide specific functionality, such as a priority queue. + * In this case, it is important to override the following methods: isMessageWaiting(), + * enqueueRequest(). + * + * @return the next message in the requestQueue. + */ + protected MessageWithMetadata getNextRequest() + { + synchronized (requestQueue) + { + int queueSize = requestQueue.size(); + + if (queueSize == 1) + { + messageWaiting = false; + } + + // return null if none left, or the next Request otherwise + return requestQueue.poll(); + } + } + + /** + * Calls processRequest(RequestMessage) on the result of getNextRequest(). + * + * In order to override functionality processRequest(RequestMessage) and/or getNextRequest() + * should be overridden. + * + */ + private final void processNextMessageAndSendResponse() + { + this.processRequest(this.getNextRequest()); + } + + /** + * Calls performService(requestMessage), then converts the resulting ResponseMessage into a + * String, adds the HTTP-like headers, and passes the completed String to the server backend for + * sending to the client. + * + * @param request + * - the request message to process. + */ + protected final ResponseMessage processRequest( + MessageWithMetadata requestWithMetadata) + { + RequestMessage request = requestWithMetadata.getMessage(); + + ResponseMessage response = super.processRequest(request, ((SocketChannel) this.socketKey + .channel()).socket().getInetAddress()); + + if (response != null) + { // if the response is null, then we do + // nothing else + sendResponseToClient(requestWithMetadata, response, request); + } + else + { + debug("context manager did not produce a response message."); + } + + requestWithMetadata = reqPool.release(requestWithMetadata); + + return response; + } + + private synchronized void sendResponseToClient( + MessageWithMetadata requestWithMetadata, ResponseMessage response, + RequestMessage request) + { + + StringBuilder msgBufOutgoing = this.frontend.getSharedStringBuilderPool().acquire(); + + try + { + // setup outgoingMessageBuffer + this.translateResponseMessageToStringBufferContents(request, response, msgBufOutgoing); + } + catch (SIMPLTranslationException e1) + { + e1.printStackTrace(); + } + + try + { + ByteBuffer compressedMessageBuffer = null; + CharBuffer outgoingChars = this.frontend.getSharedCharBufferPool().acquire(); + + boolean usingCompression = this.availableEncodings.contains(HTTP_DEFLATE_ENCODING); + /* + * If Compressing must know the length of the data being sent so must compress here + */ + if (usingCompression) + { + compressedMessageBuffer = this.frontend.getSharedByteBufferPool().acquire(); + compressedMessageBuffer.clear(); + this.compress(msgBufOutgoing, compressedMessageBuffer); + compressedMessageBuffer.flip(); + this.clearOutgoingMessageBuffer(msgBufOutgoing); + } + + this.clearOutgoingMessageHeaderBuffer(headerBufOutgoing); + + // setup outgoingMessageHeaderBuffer + this.createHeader((usingCompression) ? compressedMessageBuffer.limit() : msgBufOutgoing + .length(), headerBufOutgoing, request, response, requestWithMetadata.getUid()); + + if (usingCompression) + { + headerBufOutgoing.append(HTTP_HEADER_LINE_DELIMITER); + headerBufOutgoing.append(HTTP_CONTENT_CODING); + headerBufOutgoing.append(":"); + headerBufOutgoing.append(HTTP_DEFLATE_ENCODING); + } + + headerBufOutgoing.append(HTTP_HEADER_TERMINATOR); + + // move the characters from the outgoing buffers into + // outgoingChars using bulk get and put methods + outgoingChars.clear(); + + headerBufOutgoing.getChars(0, headerBufOutgoing.length(), outgoingChars.array(), 0); + + if (!usingCompression) + { + // assert that the size of the message is smaller than the buffer. + // if not, increase the buffer. + if (msgBufOutgoing.length() + headerBufOutgoing.length() > outgoingChars.capacity()) + { + int newCapacity = outgoingChars.capacity()*2; + this.frontend.increaseSharedBufferPoolSize(newCapacity); + outgoingChars = this.frontend.getSharedCharBufferPool().acquire(); + } + + msgBufOutgoing.getChars(0, msgBufOutgoing.length(), outgoingChars.array(), + headerBufOutgoing.length()); + + outgoingChars.limit(headerBufOutgoing.length() + msgBufOutgoing.length()); + + this.clearOutgoingMessageBuffer(msgBufOutgoing); + } + else + { + outgoingChars.limit(headerBufOutgoing.length()); + } + + outgoingChars.position(0); + + ByteBuffer outgoingBuffer = this.server.acquireByteBufferFromPool(); + + synchronized (encoder) + { + encoder.reset(); + + encoder.encode(outgoingChars, outgoingBuffer, true); + + encoder.flush(outgoingBuffer); + } + + this.frontend.getSharedCharBufferPool().release(outgoingChars); + + if (usingCompression) + { + outgoingBuffer.put(compressedMessageBuffer); + this.frontend.getSharedByteBufferPool().release(compressedMessageBuffer); + } + + server.enqueueBytesForWriting(this.socketKey, outgoingBuffer); + } + catch (DataFormatException e) + { + debug("Failed to compress response!"); + e.printStackTrace(); + } + finally + { + this.frontend.getSharedStringBuilderPool().release(msgBufOutgoing); + } + + // debug("...done ("+(System.currentTimeMillis()-currentTime)+"ms)"); + } + + @Override + public synchronized void sendUpdateToClient(UpdateMessage update) + { + StringBuilder msgBufOutgoing = this.frontend.getSharedStringBuilderPool().acquire(); + + if (this.isInvalidating()) + { + return; + } + try + { + // setup outgoingMessageBuffer + SimplTypesScope.serialize(update, msgBufOutgoing, StringFormat.XML); + } + catch (SIMPLTranslationException e1) + { + e1.printStackTrace(); + } + + try + { + ByteBuffer compressedMessageBuffer = null; + CharBuffer outgoingChars = this.frontend.getSharedCharBufferPool().acquire(); + + boolean usingCompression = this.availableEncodings.contains(HTTP_DEFLATE_ENCODING); + /* + * If Compressing must know the length of the data being sent so must compress here + */ + if (usingCompression) + { + compressedMessageBuffer = this.frontend.getSharedByteBufferPool().acquire(); + + compressedMessageBuffer.clear(); + this.compress(msgBufOutgoing, compressedMessageBuffer); + compressedMessageBuffer.flip(); + this.clearOutgoingMessageBuffer(msgBufOutgoing); + } + + this.clearOutgoingMessageHeaderBuffer(headerBufOutgoing); + + // setup outgoingMessageHeaderBuffer + this.makeUpdateHeader((usingCompression) ? compressedMessageBuffer.limit() : msgBufOutgoing + .length(), headerBufOutgoing, update); + + if (usingCompression) + { + headerBufOutgoing.append(HTTP_HEADER_LINE_DELIMITER); + headerBufOutgoing.append(HTTP_CONTENT_CODING); + headerBufOutgoing.append(":"); + headerBufOutgoing.append(HTTP_DEFLATE_ENCODING); + } + + headerBufOutgoing.append(HTTP_HEADER_TERMINATOR); + + // move the characters from the outgoing buffers into + // outgoingChars using bulk get and put methods + outgoingChars.clear(); + + headerBufOutgoing.getChars(0, headerBufOutgoing.length(), outgoingChars.array(), 0); + + if (!usingCompression) + { + msgBufOutgoing.getChars(0, msgBufOutgoing.length(), outgoingChars.array(), + headerBufOutgoing.length()); + + outgoingChars.limit(headerBufOutgoing.length() + msgBufOutgoing.length()); + + this.clearOutgoingMessageBuffer(msgBufOutgoing); + } + else + { + outgoingChars.limit(headerBufOutgoing.length()); + } + + outgoingChars.position(0); + + ByteBuffer outgoingBuffer = this.server.acquireByteBufferFromPool(); + + synchronized (encoder) + { + encoder.reset(); + + encoder.encode(outgoingChars, outgoingBuffer, true); + + encoder.flush(outgoingBuffer); + } + + this.frontend.getSharedCharBufferPool().release(outgoingChars); + + if (usingCompression) + { + outgoingBuffer.put(compressedMessageBuffer); + this.frontend.getSharedByteBufferPool().release(compressedMessageBuffer); + } + + server.enqueueBytesForWriting(this.socketKey, outgoingBuffer); + } + catch (DataFormatException e) + { + debug("Failed to compress update!"); + e.printStackTrace(); + } + finally + { + this.frontend.getSharedStringBuilderPool().release(msgBufOutgoing); + } + } + + private void compress(StringBuilder src, ByteBuffer dest) throws DataFormatException + { + CharBuffer zippingChars = this.frontend.getSharedCharBufferPool().acquire(); + zippingChars.clear(); + + src.getChars(0, src.length(), zippingChars.array(), 0); + zippingChars.position(0); + zippingChars.limit(src.length()); + + ByteBuffer zippingInBytes = this.frontend.getSharedByteBufferPool().acquire(); + zippingInBytes.clear(); + + encoder.reset(); + encoder.encode(zippingChars, zippingInBytes, true); + encoder.flush(zippingInBytes); + + this.frontend.getSharedCharBufferPool().release(zippingChars); + + zippingInBytes.flip(); + + deflater.reset(); + deflater.setInput(zippingInBytes.array(), zippingInBytes.position(), zippingInBytes.limit()); + deflater.finish(); + + this.frontend.getSharedByteBufferPool().release(zippingInBytes); + + dest.position(dest.position() + + deflater.deflate(dest.array(), dest.position(), dest.remaining())); + + } + + /** + * Takes an incoming message in the form of an XML String and converts it into a RequestMessage + * using translateStringToRequestMessage(String). Then places the RequestMessage on the + * requestQueue using enqueueRequest(). + * + * @param incomingMessage + * @param headerMap2 + * @throws BadClientException + */ + private final void processString(CharSequence incomingMessage, long incomingUid) + throws BadClientException + { + Exception failReason = null; + RequestMessage request = null; + try + { + request = this.translateStringToRequestMessage(incomingMessage); + } + catch (SIMPLTranslationException e) + { + // drop down to request == null, below + failReason = e; + } + catch (UnsupportedEncodingException e) + { + // drop down to request == null, below + failReason = e; + } + + if (request == null) + { + if (incomingMessage.length() > 100) + { + debug("ERROR; incoming message could not be translated: " + incomingMessage.toString()); + + debug("HEADERS:"); + debug(headerMap.toString()); + + if (failReason != null) + { + debug("EXCEPTION: " + failReason.getMessage()); + failReason.printStackTrace(); + } + } + else + { + debug("ERROR; incoming message could not be translated: " + incomingMessage.toString()); + + debug("HEADERS:"); + debug(headerMap.toString()); + + if (failReason != null) + { + debug("EXCEPTION: " + failReason.getMessage()); + failReason.printStackTrace(); + } + } + if (++badTransmissionCount >= MAXIMUM_TRANSMISSION_ERRORS) + { + throw new BadClientException(((SocketChannel) this.socketKey.channel()).socket() + .getInetAddress().getHostAddress(), "Too many Bad Transmissions: " + + badTransmissionCount); + } + // else + error("translation failed: badTransmissionCount=" + badTransmissionCount); + } + else + { + badTransmissionCount = 0; + + MessageWithMetadata pReq = this.reqPool.acquire(); + + pReq.setMessage(request); + pReq.setUid(incomingUid); + + synchronized (requestQueue) + { + this.enqueueRequest(pReq); + } + } + } + + @Override + public InetSocketAddress getAddress() + { + return (InetSocketAddress) ((SocketChannel) getSocketKey().channel()).socket() + .getRemoteSocketAddress(); + + } + + public SessionHandle getHandle() + { + return handle; + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/package.html b/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/package.html index f5f0222f..37514378 100644 --- a/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/package.html +++ b/simplCore/src/ecologylab/oodss/distributed/server/clientsessionmanager/package.html @@ -1,7 +1,7 @@ - - Base and custom context managers for NIO-based servers. - Context managers handle each client-server connection on - the server side, and can be customized to provide extra - functionality. - - + + Base and custom context managers for NIO-based servers. + Context managers handle each client-server connection on + the server side, and can be customized to provide extra + functionality. + + diff --git a/simplCore/src/ecologylab/oodss/distributed/server/package.html b/simplCore/src/ecologylab/oodss/distributed/server/package.html index 225f8ecf..eb11a264 100644 --- a/simplCore/src/ecologylab/oodss/distributed/server/package.html +++ b/simplCore/src/ecologylab/oodss/distributed/server/package.html @@ -1,3 +1,3 @@ - -Interface Ecology Lab Distributed Services Framework -- NIO servers. - + +Interface Ecology Lab Distributed Services Framework -- NIO servers. + diff --git a/simplCore/src/ecologylab/oodss/distributed/server/varieties/HttpGetServer.java b/simplCore/src/ecologylab/oodss/distributed/server/varieties/HttpGetServer.java index 02ccede0..89a33dcf 100644 --- a/simplCore/src/ecologylab/oodss/distributed/server/varieties/HttpGetServer.java +++ b/simplCore/src/ecologylab/oodss/distributed/server/varieties/HttpGetServer.java @@ -1,65 +1,65 @@ -/** - * - */ -package ecologylab.oodss.distributed.server.varieties; - -import java.io.IOException; -import java.net.BindException; -import java.net.InetAddress; -import java.nio.channels.SelectionKey; - -import ecologylab.collections.Scope; -import ecologylab.oodss.distributed.server.DoubleThreadedNIOServer; -import ecologylab.oodss.distributed.server.clientsessionmanager.HTTPGetClientSessionManager; -import ecologylab.serialization.SimplTypesScope; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class HttpGetServer extends DoubleThreadedNIOServer -{ - /** - * @param portNumber - * @param inetAddresses - * @param requestTranslationSpace - * @param objectRegistry - * @param idleConnectionTimeout - * @param maxPacketSize - * @throws IOException - * @throws BindException - */ - public HttpGetServer(int portNumber, InetAddress[] inetAddresses, - SimplTypesScope requestTranslationSpace, Scope objectRegistry, int idleConnectionTimeout, - int maxPacketSize) throws IOException, BindException - { - super(portNumber, inetAddresses, requestTranslationSpace, objectRegistry, - idleConnectionTimeout, maxPacketSize); - } - - /** - * @param portNumber - * @param inetAddress - * @param requestTranslationSpace - * @param objectRegistry - * @param idleConnectionTimeout - * @param maxPacketSize - * @throws IOException - * @throws BindException - */ - public HttpGetServer(int portNumber, InetAddress inetAddress, - SimplTypesScope requestTranslationSpace, Scope objectRegistry, int idleConnectionTimeout, - int maxPacketSize) throws IOException, BindException - { - super(portNumber, inetAddress, requestTranslationSpace, objectRegistry, idleConnectionTimeout, - maxPacketSize); - } - - @Override - protected HTTPGetClientSessionManager generateContextManager(String token, SelectionKey sk, - SimplTypesScope translationScopeIn, Scope registryIn) - { - return new HTTPGetClientSessionManager(token, maxMessageSize, this.getBackend(), this, sk, - translationScopeIn, registryIn); - } -} +/** + * + */ +package ecologylab.oodss.distributed.server.varieties; + +import java.io.IOException; +import java.net.BindException; +import java.net.InetAddress; +import java.nio.channels.SelectionKey; + +import ecologylab.collections.Scope; +import ecologylab.oodss.distributed.server.DoubleThreadedNIOServer; +import ecologylab.oodss.distributed.server.clientsessionmanager.HTTPGetClientSessionManager; +import ecologylab.serialization.SimplTypesScope; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class HttpGetServer extends DoubleThreadedNIOServer +{ + /** + * @param portNumber + * @param inetAddresses + * @param requestTranslationSpace + * @param objectRegistry + * @param idleConnectionTimeout + * @param maxPacketSize + * @throws IOException + * @throws BindException + */ + public HttpGetServer(int portNumber, InetAddress[] inetAddresses, + SimplTypesScope requestTranslationSpace, Scope objectRegistry, int idleConnectionTimeout, + int maxPacketSize) throws IOException, BindException + { + super(portNumber, inetAddresses, requestTranslationSpace, objectRegistry, + idleConnectionTimeout, maxPacketSize); + } + + /** + * @param portNumber + * @param inetAddress + * @param requestTranslationSpace + * @param objectRegistry + * @param idleConnectionTimeout + * @param maxPacketSize + * @throws IOException + * @throws BindException + */ + public HttpGetServer(int portNumber, InetAddress inetAddress, + SimplTypesScope requestTranslationSpace, Scope objectRegistry, int idleConnectionTimeout, + int maxPacketSize) throws IOException, BindException + { + super(portNumber, inetAddress, requestTranslationSpace, objectRegistry, idleConnectionTimeout, + maxPacketSize); + } + + @Override + protected HTTPGetClientSessionManager generateContextManager(String token, SelectionKey sk, + SimplTypesScope translationScopeIn, Scope registryIn) + { + return new HTTPGetClientSessionManager(token, maxMessageSize, this.getBackend(), this, sk, + translationScopeIn, registryIn); + } +} diff --git a/simplCore/src/ecologylab/oodss/exceptions/BadClientException.java b/simplCore/src/ecologylab/oodss/exceptions/BadClientException.java index 66f4b98a..af14ab32 100644 --- a/simplCore/src/ecologylab/oodss/exceptions/BadClientException.java +++ b/simplCore/src/ecologylab/oodss/exceptions/BadClientException.java @@ -1,166 +1,166 @@ -/** - * - */ -package ecologylab.oodss.exceptions; - -import java.util.HashMap; - -import ecologylab.generic.Debug; - -/** - * Throw this Exception when we detect that the client is evil or lame. - * - * @author andruid - * - */ -public class BadClientException extends Exception -{ - /** - * - */ - private static final long serialVersionUID = 1652784829579621254L; - - private static HashMap evilHostsMap = new HashMap(); - - /** - * Time for which a seemingly evil host gets locked out. Currently 20 minutes. - */ - public static final long LOCKOUT_INTERVAL = 20 * 60 * 1000; - - /** - * Time in which bad responses from a host define it as evil host. Currently 1 minute. - */ - public static final long REPEAT_OFFENDER_INTERVAL = 60 * 1000; - - public static final int BAD_OFFENSE_THRESHOLD = 3; - - // TODO make all call sites pass IP number in - // TODO make call site in timeoutBeforeValidMsg also pass timeStamp in. - - /** - * Report that the client has behaved badly, by sending an improperly formed message. - * - * @param message - */ - public BadClientException(String ipNumber, String message) - { - this(ipNumber, System.currentTimeMillis(), message); - } - - /** - * Report that the client has behaved badly, by timing out. - * - * @param message - */ - public BadClientException(String ipNumber, long timeStamp, String message) - { - super(message); - badClientIncident(ipNumber, timeStamp); - Debug.println(ipNumber + " flagged because " + message); - } - - static class EvilHostEntry - { - long timeStamp; - - int count; - - EvilHostEntry(long timeStamp) - { - this.timeStamp = timeStamp; - } - - EvilHostEntry() - { - this(System.currentTimeMillis()); - } - - void badClientIncident(long newTimeStamp) - { - count++; - this.timeStamp = newTimeStamp; - } - - void badClientIncident() - { - badClientIncident(System.currentTimeMillis()); - } - - boolean isEvil() - { - return (System.currentTimeMillis() - timeStamp) < LOCKOUT_INTERVAL; - } - } - - static class OkEvilHostEntry extends EvilHostEntry - { - OkEvilHostEntry() - { - - } - - @Override boolean isEvil() - { - return false; - } - } - - static final EvilHostEntry OK_HOST_ENTRY = new OkEvilHostEntry(); - - public static boolean isEvilHostByNumber(String ipNumber) - { - Debug.println("I'm looking up " + ipNumber); - for (String s : evilHostsMap.keySet()) - { - Debug.println(s); - } - EvilHostEntry entry = evilHostsMap.get(ipNumber); - if (entry == null) - { - synchronized (evilHostsMap) - { - entry = evilHostsMap.get(ipNumber); - if (entry == null) - { - entry = OK_HOST_ENTRY; - evilHostsMap.put(ipNumber, OK_HOST_ENTRY); - } - } - } - - Debug.println(ipNumber + " is evil? " + entry.isEvil()); - - return entry.isEvil(); - } - - /** - * Register a BadClientException incident for this host. - * - * @param ipNumber - * Host that was bad. - * @param timeStamp - * When the bad event occurred - * - * @return true if now the host is considered to be evil. - */ - private static boolean badClientIncident(String ipNumber, long timeStamp) - { - Debug.println("client at " + ipNumber + " was naughty and is going into timeout."); - EvilHostEntry entry = evilHostsMap.get(ipNumber); - if ((entry == null) || (entry == OK_HOST_ENTRY)) - { - synchronized (evilHostsMap) - { - entry = evilHostsMap.get(ipNumber); - if ((entry == null) || (entry == OK_HOST_ENTRY)) - { - entry = new EvilHostEntry(timeStamp); - evilHostsMap.put(ipNumber, entry); - } - } - } - entry.badClientIncident(timeStamp); - return entry.isEvil(); - - } -} +/** + * + */ +package ecologylab.oodss.exceptions; + +import java.util.HashMap; + +import ecologylab.generic.Debug; + +/** + * Throw this Exception when we detect that the client is evil or lame. + * + * @author andruid + * + */ +public class BadClientException extends Exception +{ + /** + * + */ + private static final long serialVersionUID = 1652784829579621254L; + + private static HashMap evilHostsMap = new HashMap(); + + /** + * Time for which a seemingly evil host gets locked out. Currently 20 minutes. + */ + public static final long LOCKOUT_INTERVAL = 20 * 60 * 1000; + + /** + * Time in which bad responses from a host define it as evil host. Currently 1 minute. + */ + public static final long REPEAT_OFFENDER_INTERVAL = 60 * 1000; + + public static final int BAD_OFFENSE_THRESHOLD = 3; + + // TODO make all call sites pass IP number in + // TODO make call site in timeoutBeforeValidMsg also pass timeStamp in. + + /** + * Report that the client has behaved badly, by sending an improperly formed message. + * + * @param message + */ + public BadClientException(String ipNumber, String message) + { + this(ipNumber, System.currentTimeMillis(), message); + } + + /** + * Report that the client has behaved badly, by timing out. + * + * @param message + */ + public BadClientException(String ipNumber, long timeStamp, String message) + { + super(message); + badClientIncident(ipNumber, timeStamp); + Debug.println(ipNumber + " flagged because " + message); + } + + static class EvilHostEntry + { + long timeStamp; + + int count; + + EvilHostEntry(long timeStamp) + { + this.timeStamp = timeStamp; + } + + EvilHostEntry() + { + this(System.currentTimeMillis()); + } + + void badClientIncident(long newTimeStamp) + { + count++; + this.timeStamp = newTimeStamp; + } + + void badClientIncident() + { + badClientIncident(System.currentTimeMillis()); + } + + boolean isEvil() + { + return (System.currentTimeMillis() - timeStamp) < LOCKOUT_INTERVAL; + } + } + + static class OkEvilHostEntry extends EvilHostEntry + { + OkEvilHostEntry() + { + + } + + @Override boolean isEvil() + { + return false; + } + } + + static final EvilHostEntry OK_HOST_ENTRY = new OkEvilHostEntry(); + + public static boolean isEvilHostByNumber(String ipNumber) + { + Debug.println("I'm looking up " + ipNumber); + for (String s : evilHostsMap.keySet()) + { + Debug.println(s); + } + EvilHostEntry entry = evilHostsMap.get(ipNumber); + if (entry == null) + { + synchronized (evilHostsMap) + { + entry = evilHostsMap.get(ipNumber); + if (entry == null) + { + entry = OK_HOST_ENTRY; + evilHostsMap.put(ipNumber, OK_HOST_ENTRY); + } + } + } + + Debug.println(ipNumber + " is evil? " + entry.isEvil()); + + return entry.isEvil(); + } + + /** + * Register a BadClientException incident for this host. + * + * @param ipNumber + * Host that was bad. + * @param timeStamp + * When the bad event occurred + * + * @return true if now the host is considered to be evil. + */ + private static boolean badClientIncident(String ipNumber, long timeStamp) + { + Debug.println("client at " + ipNumber + " was naughty and is going into timeout."); + EvilHostEntry entry = evilHostsMap.get(ipNumber); + if ((entry == null) || (entry == OK_HOST_ENTRY)) + { + synchronized (evilHostsMap) + { + entry = evilHostsMap.get(ipNumber); + if ((entry == null) || (entry == OK_HOST_ENTRY)) + { + entry = new EvilHostEntry(timeStamp); + evilHostsMap.put(ipNumber, entry); + } + } + } + entry.badClientIncident(timeStamp); + return entry.isEvil(); + + } +} diff --git a/simplCore/src/ecologylab/oodss/exceptions/ClientOfflineException.java b/simplCore/src/ecologylab/oodss/exceptions/ClientOfflineException.java index e14aacaa..091d7156 100644 --- a/simplCore/src/ecologylab/oodss/exceptions/ClientOfflineException.java +++ b/simplCore/src/ecologylab/oodss/exceptions/ClientOfflineException.java @@ -1,51 +1,51 @@ -/** - * - */ -package ecologylab.oodss.exceptions; - -/** - * Exception indicating that an operation failed because the client is no longer connected. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class ClientOfflineException extends Exception -{ - private static final long serialVersionUID = 1L; - - /** - * - */ - public ClientOfflineException() - { - } - - /** - * @param arg0 - */ - public ClientOfflineException(String arg0) - { - super(arg0); - // TODO Auto-generated constructor stub - } - - /** - * @param arg0 - */ - public ClientOfflineException(Throwable arg0) - { - super(arg0); - // TODO Auto-generated constructor stub - } - - /** - * @param arg0 - * @param arg1 - */ - public ClientOfflineException(String arg0, Throwable arg1) - { - super(arg0, arg1); - // TODO Auto-generated constructor stub - } - -} +/** + * + */ +package ecologylab.oodss.exceptions; + +/** + * Exception indicating that an operation failed because the client is no longer connected. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class ClientOfflineException extends Exception +{ + private static final long serialVersionUID = 1L; + + /** + * + */ + public ClientOfflineException() + { + } + + /** + * @param arg0 + */ + public ClientOfflineException(String arg0) + { + super(arg0); + // TODO Auto-generated constructor stub + } + + /** + * @param arg0 + */ + public ClientOfflineException(Throwable arg0) + { + super(arg0); + // TODO Auto-generated constructor stub + } + + /** + * @param arg0 + * @param arg1 + */ + public ClientOfflineException(String arg0, Throwable arg1) + { + super(arg0, arg1); + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/oodss/exceptions/SaveFailedException.java b/simplCore/src/ecologylab/oodss/exceptions/SaveFailedException.java index 32371bf4..2964d17b 100644 --- a/simplCore/src/ecologylab/oodss/exceptions/SaveFailedException.java +++ b/simplCore/src/ecologylab/oodss/exceptions/SaveFailedException.java @@ -1,47 +1,47 @@ -/** - * - */ -package ecologylab.oodss.exceptions; - -/** - * Indicates that a call to save() failed. The actual exception that caused the failure is provided. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class SaveFailedException extends Exception -{ - private static final long serialVersionUID = 1L; - - /** - * - */ - public SaveFailedException() - { - super(); - } - - /** - * @param message - * @param cause - */ - public SaveFailedException(String message, Throwable cause) - { - super(message, cause); - } - - /** - * @param message - */ - public SaveFailedException(String message) - { - super(message); - } - - /** - * @param cause - */ - public SaveFailedException(Throwable cause) - { - super(cause); - } -} +/** + * + */ +package ecologylab.oodss.exceptions; + +/** + * Indicates that a call to save() failed. The actual exception that caused the failure is provided. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class SaveFailedException extends Exception +{ + private static final long serialVersionUID = 1L; + + /** + * + */ + public SaveFailedException() + { + super(); + } + + /** + * @param message + * @param cause + */ + public SaveFailedException(String message, Throwable cause) + { + super(message, cause); + } + + /** + * @param message + */ + public SaveFailedException(String message) + { + super(message); + } + + /** + * @param cause + */ + public SaveFailedException(Throwable cause) + { + super(cause); + } +} diff --git a/simplCore/src/ecologylab/oodss/exceptions/package.html b/simplCore/src/ecologylab/oodss/exceptions/package.html index 898409ec..c5c6dee9 100644 --- a/simplCore/src/ecologylab/oodss/exceptions/package.html +++ b/simplCore/src/ecologylab/oodss/exceptions/package.html @@ -1,3 +1,3 @@ - -Interface Ecology Lab Services Exceptions. - + +Interface Ecology Lab Services Exceptions. + diff --git a/simplCore/src/ecologylab/oodss/logging/BasicOp.java b/simplCore/src/ecologylab/oodss/logging/BasicOp.java index f96fa4b6..2a7008fd 100644 --- a/simplCore/src/ecologylab/oodss/logging/BasicOp.java +++ b/simplCore/src/ecologylab/oodss/logging/BasicOp.java @@ -1,48 +1,48 @@ -package ecologylab.oodss.logging; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * A basic operation that only logs the time that operation took place. - * - * @author alexgrau - */ -abstract public @simpl_inherit -class BasicOp extends ElementState -{ - /** Elapsed time since the session started. */ - @simpl_scalar - protected long sessionTime; - - /** No-argument constructor for XML translation. */ - public BasicOp() - { - super(); - } - - /** - * Sets the session time immediately before translating to XML. The session time is based from the - * time the log started recording. - * - * @see ecologylab.serialization.ElementState#serializationPreHook() - */ - @Override - public void serializationPreHook(TranslationContext translationContext) - { - // this.sessionTime = System.currentTimeMillis() - Logging.sessionStartTime(); - } - - /** @return the sessionTime */ - public long getSessionTime() - { - return sessionTime; - } - - /** Free resources associated with this. */ - public void recycle(boolean invert) - { - } -} +package ecologylab.oodss.logging; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * A basic operation that only logs the time that operation took place. + * + * @author alexgrau + */ +abstract public @simpl_inherit +class BasicOp extends ElementState +{ + /** Elapsed time since the session started. */ + @simpl_scalar + protected long sessionTime; + + /** No-argument constructor for XML translation. */ + public BasicOp() + { + super(); + } + + /** + * Sets the session time immediately before translating to XML. The session time is based from the + * time the log started recording. + * + * @see ecologylab.serialization.ElementState#serializationPreHook() + */ + @Override + public void serializationPreHook(TranslationContext translationContext) + { + // this.sessionTime = System.currentTimeMillis() - Logging.sessionStartTime(); + } + + /** @return the sessionTime */ + public long getSessionTime() + { + return sessionTime; + } + + /** Free resources associated with this. */ + public void recycle(boolean invert) + { + } +} diff --git a/simplCore/src/ecologylab/oodss/logging/Epilogue.java b/simplCore/src/ecologylab/oodss/logging/Epilogue.java index 5428ac5c..10adebb3 100644 --- a/simplCore/src/ecologylab/oodss/logging/Epilogue.java +++ b/simplCore/src/ecologylab/oodss/logging/Epilogue.java @@ -1,21 +1,21 @@ -package ecologylab.oodss.logging; - -import ecologylab.serialization.ElementState; - -/** - * Request message about letting the server to write closing block for xml logs and close the log file. - * - * Subclasses may provide additional information that is written to the end of a log. - * - * @author eunyee - */ -public class Epilogue extends ElementState -{ - /* - * Constructor for automatic translation; - */ - public Epilogue() - { - super(); - } -} +package ecologylab.oodss.logging; + +import ecologylab.serialization.ElementState; + +/** + * Request message about letting the server to write closing block for xml logs and close the log file. + * + * Subclasses may provide additional information that is written to the end of a log. + * + * @author eunyee + */ +public class Epilogue extends ElementState +{ + /* + * Constructor for automatic translation; + */ + public Epilogue() + { + super(); + } +} diff --git a/simplCore/src/ecologylab/oodss/logging/LogEvent.java b/simplCore/src/ecologylab/oodss/logging/LogEvent.java index f2d2c8db..4b89c9cc 100644 --- a/simplCore/src/ecologylab/oodss/logging/LogEvent.java +++ b/simplCore/src/ecologylab/oodss/logging/LogEvent.java @@ -1,119 +1,119 @@ -package ecologylab.oodss.logging; - -import java.io.IOException; -import java.io.Writer; - -import ecologylab.generic.StringTools; -import ecologylab.oodss.messages.ErrorResponse; -import ecologylab.oodss.messages.OkResponse; -import ecologylab.oodss.messages.RequestMessage; -import ecologylab.oodss.messages.ResponseMessage; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Transport for getting log data to the server, without need for any additional translation. - * - * Pre-translated XML fragments are loaded into the internal buffer, and then serialized to a server - * with this class. - * - * To facilitate logging, this object writes its contents to a Writer (generally a file) during its - * performService method. The Writer must be configured prior to invoking this method by calling the - * setWriter method. This sequence is automatically handled by a Logging server in its - * LoggingContextManager. - * - * @author eunyee - * @author andruid - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -@simpl_inherit -abstract public class LogEvent extends RequestMessage -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF_CDATA) - protected StringBuilder bufferToLog; - - /** No argument constructor for serialization. */ - public LogEvent() - { - super(); - } - - /** - * Construct a new LogRequestMessage with a specific buffer size, to prevent unnecessary - * allocation later. - */ - public LogEvent(int bufferSize) - { - bufferToLog = new StringBuilder(bufferSize); - } - - /** - * Save the logging messages to the pre-set writer. - */ - @Override - public ResponseMessage performService(LoggingContextScope contextScope) - { - debug("received logging event"); - - Writer outputStreamWriter = contextScope.getOutputStreamWriter(); - - if (outputStreamWriter != null) - { - try - { - final StringBuilder bufferToLog = bufferToLog(); - - debug(bufferToLog); - - outputStreamWriter.append(bufferToLog); - clear(); - - return OkResponse.get(); - } - catch (IOException e) - { - e.printStackTrace(); - - return new ErrorResponse(e.getMessage()); - } - } - else - { - error("can't log because there is no outputStreamWriter; was there a prologue?"); - - return new ErrorResponse( - "can't log because there is no outputStreamWriter; was there a prologue?"); - } - } - - public void setBuffer(StringBuilder bufferToLog) - { - clear(); - this.bufferToLog = bufferToLog; - } - - /** - * Stuff to write to the log file based on the contents of this message. - * - * @return ops, the buffer in which MixedInitiativeOps have been passed here. - */ - protected StringBuilder bufferToLog() - { - return bufferToLog; - } - - /** - * Clear the buffer for re-use, presumably after sending it. - */ - public void clear() - { - if (bufferToLog != null) - { - StringTools.clear(bufferToLog); - bufferToLog = null; - } - } +package ecologylab.oodss.logging; + +import java.io.IOException; +import java.io.Writer; + +import ecologylab.generic.StringTools; +import ecologylab.oodss.messages.ErrorResponse; +import ecologylab.oodss.messages.OkResponse; +import ecologylab.oodss.messages.RequestMessage; +import ecologylab.oodss.messages.ResponseMessage; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Transport for getting log data to the server, without need for any additional translation. + * + * Pre-translated XML fragments are loaded into the internal buffer, and then serialized to a server + * with this class. + * + * To facilitate logging, this object writes its contents to a Writer (generally a file) during its + * performService method. The Writer must be configured prior to invoking this method by calling the + * setWriter method. This sequence is automatically handled by a Logging server in its + * LoggingContextManager. + * + * @author eunyee + * @author andruid + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +@simpl_inherit +abstract public class LogEvent extends RequestMessage +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF_CDATA) + protected StringBuilder bufferToLog; + + /** No argument constructor for serialization. */ + public LogEvent() + { + super(); + } + + /** + * Construct a new LogRequestMessage with a specific buffer size, to prevent unnecessary + * allocation later. + */ + public LogEvent(int bufferSize) + { + bufferToLog = new StringBuilder(bufferSize); + } + + /** + * Save the logging messages to the pre-set writer. + */ + @Override + public ResponseMessage performService(LoggingContextScope contextScope) + { + debug("received logging event"); + + Writer outputStreamWriter = contextScope.getOutputStreamWriter(); + + if (outputStreamWriter != null) + { + try + { + final StringBuilder bufferToLog = bufferToLog(); + + debug(bufferToLog); + + outputStreamWriter.append(bufferToLog); + clear(); + + return OkResponse.get(); + } + catch (IOException e) + { + e.printStackTrace(); + + return new ErrorResponse(e.getMessage()); + } + } + else + { + error("can't log because there is no outputStreamWriter; was there a prologue?"); + + return new ErrorResponse( + "can't log because there is no outputStreamWriter; was there a prologue?"); + } + } + + public void setBuffer(StringBuilder bufferToLog) + { + clear(); + this.bufferToLog = bufferToLog; + } + + /** + * Stuff to write to the log file based on the contents of this message. + * + * @return ops, the buffer in which MixedInitiativeOps have been passed here. + */ + protected StringBuilder bufferToLog() + { + return bufferToLog; + } + + /** + * Clear the buffer for re-use, presumably after sending it. + */ + public void clear() + { + if (bufferToLog != null) + { + StringTools.clear(bufferToLog); + bufferToLog = null; + } + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/oodss/logging/LogOps.java b/simplCore/src/ecologylab/oodss/logging/LogOps.java index 3e06daf9..02e1efda 100644 --- a/simplCore/src/ecologylab/oodss/logging/LogOps.java +++ b/simplCore/src/ecologylab/oodss/logging/LogOps.java @@ -1,59 +1,59 @@ -package ecologylab.oodss.logging; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * Bundle a sequence of {@link MixedInitiativeOp MixedInitiativeOp}s, and send them to the logging - * server. - * - * @author eunyee - * @author andruid - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_inherit -public final class LogOps extends LogEvent -{ - /** Constructor for XML translation. */ - public LogOps() - { - super(); - } - - public LogOps(int bufferSize) - { - super(bufferSize); - } - - static final Class[] CLASSES = - { LogOps.class, LogEvent.class }; - - static final SimplTypesScope TS = SimplTypesScope.get("lo", CLASSES); - - public static void main(String[] a) - { - LogOps l = new LogOps(); - - l.bufferToLog = new StringBuilder( - ""); - - try - { - SimplTypesScope.serialize(l, System.out, StringFormat.XML); - - StringBuilder buffy = SimplTypesScope.serialize(l, StringFormat.XML); - System.out.println(""); - Object l2 = TS.deserialize(buffy.toString(), StringFormat.XML); - - SimplTypesScope.serialize(l2, System.out, StringFormat.XML); - - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } +package ecologylab.oodss.logging; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * Bundle a sequence of {@link MixedInitiativeOp MixedInitiativeOp}s, and send them to the logging + * server. + * + * @author eunyee + * @author andruid + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_inherit +public final class LogOps extends LogEvent +{ + /** Constructor for XML translation. */ + public LogOps() + { + super(); + } + + public LogOps(int bufferSize) + { + super(bufferSize); + } + + static final Class[] CLASSES = + { LogOps.class, LogEvent.class }; + + static final SimplTypesScope TS = SimplTypesScope.get("lo", CLASSES); + + public static void main(String[] a) + { + LogOps l = new LogOps(); + + l.bufferToLog = new StringBuilder( + ""); + + try + { + SimplTypesScope.serialize(l, System.out, StringFormat.XML); + + StringBuilder buffy = SimplTypesScope.serialize(l, StringFormat.XML); + System.out.println(""); + Object l2 = TS.deserialize(buffy.toString(), StringFormat.XML); + + SimplTypesScope.serialize(l2, System.out, StringFormat.XML); + + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/oodss/logging/Logging.java b/simplCore/src/ecologylab/oodss/logging/Logging.java index c13fd26e..fc623881 100644 --- a/simplCore/src/ecologylab/oodss/logging/Logging.java +++ b/simplCore/src/ecologylab/oodss/logging/Logging.java @@ -1,1177 +1,1177 @@ -package ecologylab.oodss.logging; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.channels.FileChannel.MapMode; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; -import java.nio.charset.CharsetEncoder; -import java.util.ArrayList; - -import ecologylab.appframework.ApplicationEnvironment; -import ecologylab.appframework.Memory; -import ecologylab.appframework.PropertiesAndDirectories; -import ecologylab.appframework.types.prefs.Pref; -import ecologylab.collections.Scope; -import ecologylab.generic.Debug; -import ecologylab.generic.Generic; -import ecologylab.generic.StartAndStoppable; -import ecologylab.io.Files; -import ecologylab.oodss.distributed.client.NIOClient; -import ecologylab.oodss.distributed.common.NetworkingConstants; -import ecologylab.oodss.distributed.common.ServicesHostsAndPorts; -import ecologylab.oodss.distributed.exception.MessageTooLargeException; -import ecologylab.oodss.messages.DefaultServicesTranslations; -import ecologylab.oodss.messages.ResponseMessage; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_scope; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * Provides a framework for interaction logging. Uses ecologylab.serialization to serialize user and - * agent actions, and write them either to a file on the user's local machine, or, across the - * network, to the LoggingServer. - * - * @author andruid - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class Logging extends ElementState implements - StartAndStoppable, ServicesHostsAndPorts -{ - public static final String MIXED_INITIATIVE_OP_TRANSLATION_SCOPE = "MIXED_INITIATIVE_OP_TRANSLATION_SCOPE"; - - /** - * This field is used for reading a log in from a file, but not for writing one, because we dont - * the write the log file all at once, and so can't automatically translate the start tag and end - * tag for this element. - */ - @simpl_collection - @simpl_scope(MIXED_INITIATIVE_OP_TRANSLATION_SCOPE) - protected ArrayList opSequence; - - Thread thread; - - /** - * Does all the work of logging, if there is any work to be done. If this is null, then there is - * no logging; conversely, if there is no logging, this is null. - */ - ArrayList logWriters = null; - - /** - * This is the Vector for the operations that are being queued up before they can go to - * outgoingOps. - */ - private StringBuilder incomingOpsBuffer; - - /** - * This is the Vector for the operations that are in the process of being written out. - */ - private StringBuilder outgoingOpsBuffer; - - /** Stores the pointer to outgoingOpsBuffer for swapQueues. */ - private StringBuilder tempOpsBuffer; - - static final int THREAD_PRIORITY = 1; - - /** Amount of time for writer thread to sleep; 15 seconds */ - static final int SLEEP_TIME = 15000; - - static final long sessionStartTime = System.currentTimeMillis(); - - long lastGcTime; - - /** Amount of time to wait before booting the garbage collector; 5 minutes */ - static final long KICK_GC_INTERVAL = 300000; - - private static final String SESSION_LOG_START = "\n\n "; - - static final String OP_SEQUENCE_START = "\n\n\n\n"; - - static final String OP_SEQUENCE_END = "\n\n"; - - /** Logging closing message string written to the logging file at the end */ - public static final String LOG_CLOSING = "\n\n\n"; - - /** Logging Header message string written to the logging file in the begining */ - static final String BEGIN_EMIT = XMLTools.xmlHeader() - + SESSION_LOG_START; - - /** Preference setting for no logging. */ - public static final int NO_LOGGING = 0; - - /** Preference setting for logging to a file using normal IO. */ - public static final int LOG_TO_FILE = 1; - - /** Preference setting for logging to a remote server. */ - public static final int LOG_TO_SERVICES_SERVER = 2; - - /** Preference setting for logging to a file using memory-mapped IO. */ - public static final int LOG_TO_MEMORY_MAPPED_FILE = 4; - - /** Preference setting for logging both to a memory-mapped file and a server. */ - public static final int LOG_TO_MM_FILE_AND_SERVER_REDUNDANT = LOG_TO_MEMORY_MAPPED_FILE - & LOG_TO_SERVICES_SERVER; - - /** Preference setting for logging both to a normal IO file and a server. */ - public static final int LOG_TO_FILE_AND_SERVER_REDUNDANT = LOG_TO_FILE - & LOG_TO_SERVICES_SERVER; - - static final int MAX_OPS_BEFORE_WRITE = 10; - - public static final String LOGGING_HOST_PARAM = "logging_host"; - - public static final String LOGGING_PORT_PARAM = "logging_port"; - - public static final String LOGGING_MODE_PARAM = "log_mode"; - - final int maxOpsBeforeWrite; - - final int maxBufferSizeToWrite; - - /** used to prevent writes from getting interrupt()'ed */ - private Object threadSemaphore = new Object(); - - private volatile boolean runMethodDone = false; - - volatile boolean finished; - - private boolean running = false; - - /** - * Instantiates a Logging object based on the given log file name. This constructor assumes that a - * set of loaded {@link ecologylab.appframework.types.prefs.Pref Pref}s will handle other - * settings, indicating how logging will be performed, and the server setup (if logging over a - * network). - */ - public Logging(String logFileName) - { - this(logFileName, MAX_OPS_BEFORE_WRITE); - } - - /** - * Instantiates a Logging object based on the given log file name and the maximum operations - * before write. This constructor assumes that a set of loaded - * {@link ecologylab.appframework.types.prefs.Pref Pref}s will handle other settings, indicating - * how logging will be performed, and the server setup (if logging over a network). - */ - public Logging(String logFileName, int maxOpsBeforeWrite) - { - this( logFileName, - false, - maxOpsBeforeWrite, - Pref.lookupInt(LOGGING_MODE_PARAM, NO_LOGGING), - Pref.lookupString(LOGGING_HOST_PARAM, "localhost"), - Pref.lookupInt(LOGGING_PORT_PARAM, ServicesHostsAndPorts.LOGGING_PORT), - null); - } - - /** - * Instantiates a Logging object based on the supplied parameters. This constructor does not rely - * on {@link ecologylab.appframework.types.prefs.Pref Pref}s. - * - * @param logFileName - * the name of the file to which the log will be written. - * @param logFileNameAbsolute - * TODO - * @param maxOpsBeforeWrite - * the maximum number of ops to record in memory before writing them to the set media. - * @param logMode - * the media to which the logger will write, such as a memory-mapped file or a server. - * @param loggingHost - * the host to which to log if using networked logging (may be null if local logging is - * desired). - * @param loggingPort - * the port of the host to which to log if using networked logging (may be 0 if local - * logging is desired). - * @deprecated Use {@link #Logging(String,boolean,int,int,String,int,ApplicationEnvironment)} - * instead - */ - @Deprecated - public Logging( String logFileName, - boolean logFileNameAbsolute, - int maxOpsBeforeWrite, - int logMode, - String loggingHost, - int loggingPort) - { - this( logFileName, - logFileNameAbsolute, - maxOpsBeforeWrite, - logMode, - loggingHost, - loggingPort, - null); - } - - /** - * Instantiates a Logging object based on the supplied parameters. This constructor does not rely - * on {@link ecologylab.appframework.types.prefs.Pref Pref}s. - * - * @param logFileName - * the name of the file to which the log will be written. - * @param logFileNameAbsolute - * TODO - * @param maxOpsBeforeWrite - * the maximum number of ops to record in memory before writing them to the set media. - * @param logMode - * the media to which the logger will write, such as a memory-mapped file or a server. - * @param loggingHost - * the host to which to log if using networked logging (may be null if local logging is - * desired). - * @param loggingPort - * the port of the host to which to log if using networked logging (may be 0 if local - * logging is desired). - * @param environment - * TODO - */ - public Logging( String logFileName, - boolean logFileNameAbsolute, - int maxOpsBeforeWrite, - int logMode, - String loggingHost, - int loggingPort, - ApplicationEnvironment environment) - { - this(maxOpsBeforeWrite); - - if (logMode == NO_LOGGING) - { - debug("logging disabled; NO_LOGGING specified"); - } - else - { - logWriters = new ArrayList(1); - - if ((logMode & LOG_TO_FILE) == LOG_TO_FILE) - { - if (logFileName == null) - { - debug("Logging disabled; no file name specified"); - } - else - { - File logDir; - if (!logFileNameAbsolute) - { - if (environment == null) - logDir = PropertiesAndDirectories.logDir(); - else - logDir = PropertiesAndDirectories.logDir(environment); - } - else - { - logDir = new File(logFileName); - } - - if (logDir == null) - { - debug("Can't write to logDir=" + logDir); - } - else - { - File logFile; - - if (!logFileNameAbsolute) - { - logFile = new File(logDir, logFileName); - } - else - { - logFile = logDir; - } - debug("Logging to file: " + logFile.getAbsolutePath()); - - try - { - XMLTools.createParentDirs(logFile); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - - BufferedWriter bufferedWriter = Files.openWriter(logFile); - - if (bufferedWriter != null) - { - try - { - logWriters.add(new FileLogWriter(logFile, bufferedWriter)); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - else - { - debug("ERROR: cant open writer to " + logFile); - } - } - } - } - - if ((logMode & LOG_TO_MEMORY_MAPPED_FILE) == LOG_TO_MEMORY_MAPPED_FILE) - { - if (logFileName == null) - { - debug("Logging disabled; no file name specified"); - } - else - { - File logDir; - if (!logFileNameAbsolute) - { - logDir = PropertiesAndDirectories.logDir(); - } - else - { - logDir = new File(logFileName); - } - - if (logDir == null) - { - debug("Can't write to logDir=" + logDir); - } - else - { - File logFile; - - if (!logFileNameAbsolute) - { - logFile = new File(logDir, logFileName); - } - else - { - logFile = logDir; - } - - try - { - XMLTools.createParentDirs(logFile); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - debug("Logging to file: " + logFile.getAbsolutePath()); - - try - { - logWriters.add(new MemoryMappedFileLogWriter(logFile)); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - } - } - if ((logMode & LOG_TO_SERVICES_SERVER) == LOG_TO_SERVICES_SERVER) - { - /** - * Create the logging client which communicates with the logging server - */ - if (loggingHost == null) - loggingHost = LOGGING_HOST; - - NIOClient loggingClient = null; - try - { - loggingClient = new NIOClient(loggingHost, - loggingPort, - DefaultServicesTranslations.get(), - new Scope()); - - // CONNECT TO SERVER - if (loggingClient.connect()) - { - logWriters.add(new NetworkLogWriter(loggingClient, this)); - - debug("logging to server: " + loggingHost + ":" + loggingPort); - } - else - { - loggingClient = null; - debug("Logging disabled: cannot reach server"); - } - } - catch (IOException e1) - { - e1.printStackTrace(); - } - - debug("**************************************************************connecting to server."); - - } - } - } - - /** - * Constructor for automatic translation from XML - * - */ - public Logging() - { - this(MAX_OPS_BEFORE_WRITE); - } - - protected Logging(int maxOpsBeforeWrite) - { - this.maxOpsBeforeWrite = maxOpsBeforeWrite; - final int maxBufferSizeToWrite = maxOpsBeforeWrite * 1024; - incomingOpsBuffer = new StringBuilder(maxBufferSizeToWrite); - outgoingOpsBuffer = new StringBuilder(maxBufferSizeToWrite); - this.maxBufferSizeToWrite = maxBufferSizeToWrite; - } - - private void swapBuffers() - { - synchronized (outgoingOpsBuffer) - { - synchronized (incomingOpsBuffer) - { - if (outgoingOpsBuffer.length() == 0) - { - tempOpsBuffer = outgoingOpsBuffer; - outgoingOpsBuffer = incomingOpsBuffer; - incomingOpsBuffer = tempOpsBuffer; - } - } - } - } - - /** - * Translates op to XML then logs it, if this Logging object is running. Returns true if the - * operation was placed in the buffer to be written, false if it failed (because the op could not - * be translated to XML). - * - * @param op - * - the operation to be logged. - */ - public boolean logAction(MixedInitiativeOp op) - { - if (!this.finished && logWriters != null) - { - try - { - synchronized (incomingOpsBuffer) - { - SimplTypesScope.serialize(op, incomingOpsBuffer, StringFormat.XML); - } - - // final int bufferLength = incomingOpsBuffer.length(); - // if ((thread != null) && (bufferLength > maxBufferSizeToWrite)) - // { - // synchronized (threadSemaphore) - // { - // debugA("interrupting thread to do i/o now: " + bufferLength - // + "/" + maxBufferSizeToWrite); - // thread.interrupt(); - // // end sleep in that thread prematurely to do i/o - // } - // } - - return true; - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - } - - return false; - } - - /** - * Returns the size of the list of log ops. May not be the correct value if called during logging. - * This method should only be used for playback purposes. - * - * @return the size of opSequence. - */ - public int size() - { - return this.opSequence.size(); - } - - /** - * Write the start of the log header out to the log file OR, send the begining logging file - * message so that logging server write the start of the log header. - *

- * Then start the looping thread that periodically wakes up and performs log i/o. - */ - @Override - public void start() - { - debug("Logging starting up..."); - if ((logWriters != null) && (thread == null)) - { - thread = new Thread(this); - thread.setPriority(THREAD_PRIORITY); - thread.start(); - - this.running = true; - } - } - - /** - * Finishes writing any queued actions, then sends the epilogue; then shuts down. - * - */ - @Override - public synchronized void stop() - { - debug("shutting down..."); - - if (!finished && thread != null) - { - finished = true; - - debug("initiating shutdown sequence..."); - - int timesToWait = 100; - - while (!this.runMethodDone && timesToWait-- > 0) - { - debug("waiting on run method to finish log writing (attempts remaining " + timesToWait - + ")..."); - thread.interrupt(); - Generic.sleep(500); - } - - if (timesToWait == 0) - { - debug("...giving up on waiting for run thread; continuing shutdown."); - } - else - { - debug("...done."); - } - - this.thread = null; - - synchronized (threadSemaphore) - { // since we only write from run() if we're low on memory, we may - // have all the ops still unwritten. - writeBufferedOps(); - } - - if (logWriters != null) - { - final Epilogue epilogue = getEpilogue(); - // necessary for acquiring wrapper characters, like - final SendEpilogue sendEpilogue = new SendEpilogue(this, epilogue); - - for (LogWriter logWriter : logWriters) - { - logWriter.setPriority(9); - debug("stop() writing epilogue to " + logWriter); - logWriter.writeLogMessage(sendEpilogue); - } - - // try - // { - // debug("epilogue contents: " + sendEpilogue.serialize()); - // } - // catch (SIMPLTranslationException e) - // { - // e.printStackTrace(); - // } - - synchronized (threadSemaphore) - { - debug("forcing final write"); - writeBufferedOps(); - } - - for (LogWriter logWriter : logWriters) - { - debug("stop() closing " + logWriter); - logWriter.close(); - } - - debug("...stop() finished."); - - logWriters = null; - } - } - debug("...shutdown complete."); - - this.running = false; - } - - /** - * Logging to a file is delayed to the actions of this thread, because otherwise, it can mess up - * priorities in the system, because events get logged in the highest priority thread. - *

- * This MUST be the only thread that ever calls writeQueuedActions(). - */ - @Override - public void run() - { - this.runMethodDone = false; - this.finished = false; - - final Prologue prologue = getPrologue(); - String uid = Pref.lookupString("uid", "0"); - Logging.this.debug("Logging: Sending Prologue userID:" + uid); - prologue.setUserID(uid); - - // necessary for acquiring wrapper characters, like - final SendPrologue sendPrologue = new SendPrologue(Logging.this, prologue); - - for (LogWriter logWriter : logWriters) - { - debug("sending prologue"); - logWriter.writeLogMessage(sendPrologue); - } - - lastGcTime = System.currentTimeMillis(); - while (!finished) - { - Thread.interrupted(); - Generic.sleep(SLEEP_TIME, false); - - if (finished) - debug("run thread awakened for final run"); - - if (!Memory.reclaimIfLow()) - { - synchronized (threadSemaphore) - { - writeBufferedOps(); - } - } - - if (finished) - debug("run thread finishing"); - } - - debug("run thread finished."); - // now that we are finished, we let everyone else know - this.runMethodDone = true; - } - - /** - * Use the LogWriter, if there is one, to output queued actions to the log. - *

- * NB: This method is SINGLE Threaded! It is not thread safe. It must only be called from the - * run() method. - */ - protected void writeBufferedOps() - { - StringBuilder bufferToWrite = incomingOpsBuffer; - synchronized (bufferToWrite) - { - int size = bufferToWrite.length(); - - if (size == 0) - return; - swapBuffers(); - // what was incomingOps is now outgoing! - if (logWriters != null) - { - for (LogWriter logWriter : logWriters) - { - logWriter.writeBufferedOps(bufferToWrite); - } - } - // debug("Logging: writeQueuedActions() after output loop."); - bufferToWrite.setLength(0); - } - } - - /** - * A message at the beginnging of the log. This method may be overridden to return a subclass of - * Prologue, by subclasses of this, that wish to emit application specific information at the - * start of a log. - * - * @return - */ - public Prologue getPrologue() - { - return new Prologue(); - } - - /** - * A message at the end of the log. This method may be overridden to return a subclass of - * Epilogue, by subclasses of this, that wish to emit application specific information at the end - * of a log. - * - * @return - */ - protected Epilogue getEpilogue() - { - Epilogue epilogue = new Epilogue(); - return epilogue; - } - - /** - * Return our session start timestamp. - * - * @return - */ - public static final long sessionStartTime() - { - return sessionStartTime; - } - - /** - * Objects that process queuedActions for writing, either to a local file, or, using the network, - * to the LoggingServer. - * - * @author andruid - * @author Zachary O. Toups (zach@ecologylab.net) - */ - protected abstract class LogWriter extends Debug - { - LogWriter() throws IOException - { - - } - - /** - * Get the bufferToLog() from the LogRequestMessage. Write it out! - * - * @param logRequestMessage - */ - void writeLogMessage(LogEvent logRequestMessage) - { - StringBuilder buffy = logRequestMessage.bufferToLog(); - writeLogMessage(buffy); - - } - - abstract void writeLogMessage(StringBuilder xmlBuffy); - - void writeBufferedOps(StringBuilder opsBuffer) - { - writeLogMessage(opsBuffer); - } - - abstract void close(); - - public void setPriority(int priority) - { - - } - } - - /** - * LogWriter that uses a memory-mapped local file for logging. - * - * @author andruid - * @author Zachary O. Toups (zach@ecologylab.net) - */ - protected class MemoryMappedFileLogWriter extends LogWriter - { - // BufferedWriter bufferedWriter; - MappedByteBuffer buffy = null; - - FileChannel channel = null; - - private CharsetEncoder encoder = Charset.forName(NetworkingConstants.CHARACTER_ENCODING) - .newEncoder(); - - private File logFile; - - /** - * The base size for the log file, and the amount it will be incremented whenever its buffer - * overflows. - */ - static final int LOG_FILE_INCREMENT = 1024 * 512; - - private int endOfMappedBytes = LOG_FILE_INCREMENT; - - MemoryMappedFileLogWriter(File logFile) throws IOException - { - this.logFile = logFile; - - channel = new RandomAccessFile(logFile, "rw").getChannel(); - - // allocate LOG_FILE_INCREMENT for the file size; this will be - // incremented as necessary - buffy = channel.map(MapMode.READ_WRITE, 0, LOG_FILE_INCREMENT); - - // if (bufferedWriter == null) - // throw new IOException("Can't log to File with null - // buffereredWriter."); - // this.bufferedWriter = bufferedWriter; - Logging.this.debugA("Logging to " + logFile + " " + buffy); - } - - /** - * Get the bufferToLog() from the LogRequestMessage. Write it out! - * - * @param buffer - */ - @Override - void writeLogMessage(StringBuilder buffer) - { - try - { - putInBuffer(encoder.encode(CharBuffer.wrap(buffer))); - } - catch (CharacterCodingException e) - { - e.printStackTrace(); - } - - } - - @Override - public void close() - { - try - { - buffy.force(); - - // shrink the file to the appropriate size - int fileSize = 0; - - fileSize = endOfMappedBytes - LOG_FILE_INCREMENT + buffy.position(); - - buffy = null; - - channel.close(); - - channel = null; - - // do garbage collection to ensure that the file is no longer - // mapped - System.runFinalization(); - System.gc(); - - debug("final log file size is " + fileSize + " bytes."); - - debug("truncating log."); - - boolean truncated = false; - int numTries = 0; - - while (!truncated) - { - try - { - new RandomAccessFile(logFile, "rw").getChannel().truncate(fileSize); - - truncated = true; - } - catch (IOException e) - { - debug("truncation failed because the file is still mapped, attempting to garbage collect...AGAIN."); - - // do garbage collection to ensure that the file is no - // longer mapped - System.runFinalization(); - System.gc(); - - numTries++; - } - - if (numTries == 100) - { - debug("Tried to unmap file 100 times; failing now."); - - truncated = true; - } - } - } - catch (IOException e1) - { - e1.printStackTrace(); - } - } - - private void putInBuffer(ByteBuffer incoming) - { - - try - { - int remaining = buffy.remaining(); - - if (remaining < incoming.remaining()) - { // we want to write more than will fit; so we just write - // what we can first... - debug("not enough space in the buffer: " + remaining + "/" - + incoming.remaining() + "; old range: " + (endOfMappedBytes - LOG_FILE_INCREMENT) + "-" - + endOfMappedBytes+"; new range: " + (endOfMappedBytes) + "-" - + (endOfMappedBytes + LOG_FILE_INCREMENT)); - - byte[] temp = new byte[remaining]; - incoming.get(temp, 0, remaining); - - buffy.put(temp); - - // ensure that the buffer has been written out - buffy.force(); - - // then shift buffy to map to the next segment of the file - buffy = channel.map(MapMode.READ_WRITE, endOfMappedBytes, LOG_FILE_INCREMENT); - endOfMappedBytes += LOG_FILE_INCREMENT; - - // recursively call on the remainder of incoming - putInBuffer(incoming); - } - else - { - if (show(5)) - debug("writing to buffer: " + remaining + "bytes remaining before resize"); - - buffy.put(incoming); - } - } - catch (NullPointerException e) - { - debug("null pointer; data to be written:"); - try - { - debug(Charset.forName("ASCII").newDecoder().decode(incoming).toString()); - } - catch (CharacterCodingException e1) - { - e1.printStackTrace(); - } - - e.printStackTrace(); - } - catch (CharacterCodingException e) - { - e.printStackTrace(); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - } - - /** - * LogWriter that uses a local file for logging. - * - * @author andruid - * @author Zachary O. Toups (zach@ecologylab.net) - */ - protected class FileLogWriter extends LogWriter - { - BufferedWriter bufferedWriter; - - FileLogWriter(File logFile, BufferedWriter bufferedWriter) throws IOException - { - if (bufferedWriter == null) - throw new IOException("Can't log to File with null buffereredWriter."); - this.bufferedWriter = bufferedWriter; - Logging.this.debugA("Logging to " + logFile + " " + bufferedWriter); - } - - /** - * Write the opsBuffer to a file. - */ - @Override - void writeLogMessage(StringBuilder buffy) - { - try - { - bufferedWriter.append(buffy); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - - @Override - void close() - { - try - { - bufferedWriter.close(); - } - catch (IOException e) - { - e.printStackTrace(); - } - bufferedWriter = null; - } - } - - /** - * LogWriter that connects to the ServicesServer over the network for logging. - * - * @author andruid - * @author Zachary O. Toups (zach@ecologylab.net) - */ - protected class NetworkLogWriter extends LogWriter - { - NIOClient loggingClient; - - /** Object for sending a batch of ops to the LoggingServer. */ - final LogOps logOps; - - /** - * The owner of this Logging object, used to ensure that, during shutdown, this object blocks - * until it is finished sending; needed to determine the current status. - */ - final Logging loggingParent; - - NetworkLogWriter(NIOClient loggingClient, Logging loggingParent) throws IOException - { - if (loggingClient == null) - throw new IOException("Can't log to Network with null loggingClient."); - this.loggingClient = loggingClient; - Logging.this.debug("Logging to service via connection: " + loggingClient); - - // logOps = new LogOps(maxBufferSizeToWrite); - logOps = new LogOps(); - - this.loggingParent = loggingParent; - } - - @Override - public void setPriority(int priority) - { - NIOClient loggingClient = this.loggingClient; - if (loggingClient != null) - loggingClient.setPriority(priority); - } - - /** - * Writes the given message to the logging server. Recursively calls itself if the message is - * too large to send at once. - */ - @Override - void writeLogMessage(LogEvent message) - { - try - { - if (!this.loggingParent.finished) - { - debug(">> sending a normal log message (non-blocking): "); - try - { - debug(SimplTypesScope.serialize(message, StringFormat.XML).toString()); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - loggingClient.nonBlockingSendMessage(message); - } - else - { - // finishing, wait 50 seconds - int timeOutMillis = 50000; - - debug(">> network logging finishing, waiting up to " + (timeOutMillis / 1000) - + " seconds..."); - - ResponseMessage rm = loggingClient.sendMessage(message, timeOutMillis); - - if (rm == null) - debug("!!! gave up waiting for server response after " + (timeOutMillis / 1000) - + " seconds."); - else - debug(">>> final log ops sent successfully!"); - } - } - catch (IOException e) - { - e.printStackTrace(); - } - catch (MessageTooLargeException e) - { - StringBuilder bufferToLog = message.bufferToLog(); - int half = bufferToLog.length() / 2; - - warning("!!!! attempted to send a message that was too large, splitting in half and trying again recursively (" - + bufferToLog.length() + "/2 == " + half + ")"); - - LogOps firstHalf = new LogOps(); - firstHalf.setBuffer(new StringBuilder(bufferToLog.subSequence(0, half))); - - LogOps secondHalf = new LogOps(); - secondHalf.setBuffer(new StringBuilder(bufferToLog.subSequence(half, bufferToLog.length()))); - - this.writeLogMessage(firstHalf); - this.writeLogMessage(secondHalf); - - // if (message instanceof SendPrologue) - // { // if this is a send prologue, send prologue has to happen first - // message.setBuffer(new StringBuilder(bufferToLog.subSequence(0, half))); - // this.writeLogMessage(message); - // } - // else - // { - // this.writeBufferedOps(new StringBuilder(bufferToLog.subSequence(0, half))); - // } - // - // if (message instanceof SendEpilogue) - // { // if this is a send epilogue, send epilogue has to happen last - // message.setBuffer(new StringBuilder(bufferToLog.subSequence(half, - // bufferToLog.length()))); - // this.writeLogMessage(message); - // } - // else - // { - // this.writeBufferedOps(new StringBuilder(bufferToLog.subSequence(half, bufferToLog - // .length()))); - // } - } - } - - @Override - void writeBufferedOps(StringBuilder buffy) - { - logOps.setBuffer(buffy); - - writeLogMessage(logOps); - - logOps.clear(); - buffy.setLength(0); - } - - /** - * Close the connection to the loggingServer. - */ - @Override - void close() - { - debug("close."); - - loggingClient.disconnect(); - loggingClient = null; - } - - @Override - void writeLogMessage(StringBuilder xmlBuffy) - { - throw new UnsupportedOperationException(); - } - } - - /** - * @return the opSequence - */ - public ArrayList getOpSequence() - { - return opSequence; - } - - /** - * @return the running - */ - public boolean isRunning() - { - return running; - } -} +package ecologylab.oodss.logging; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileChannel.MapMode; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.util.ArrayList; + +import ecologylab.appframework.ApplicationEnvironment; +import ecologylab.appframework.Memory; +import ecologylab.appframework.PropertiesAndDirectories; +import ecologylab.appframework.types.prefs.Pref; +import ecologylab.collections.Scope; +import ecologylab.generic.Debug; +import ecologylab.generic.Generic; +import ecologylab.generic.StartAndStoppable; +import ecologylab.io.Files; +import ecologylab.oodss.distributed.client.NIOClient; +import ecologylab.oodss.distributed.common.NetworkingConstants; +import ecologylab.oodss.distributed.common.ServicesHostsAndPorts; +import ecologylab.oodss.distributed.exception.MessageTooLargeException; +import ecologylab.oodss.messages.DefaultServicesTranslations; +import ecologylab.oodss.messages.ResponseMessage; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_scope; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * Provides a framework for interaction logging. Uses ecologylab.serialization to serialize user and + * agent actions, and write them either to a file on the user's local machine, or, across the + * network, to the LoggingServer. + * + * @author andruid + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class Logging extends ElementState implements + StartAndStoppable, ServicesHostsAndPorts +{ + public static final String MIXED_INITIATIVE_OP_TRANSLATION_SCOPE = "MIXED_INITIATIVE_OP_TRANSLATION_SCOPE"; + + /** + * This field is used for reading a log in from a file, but not for writing one, because we dont + * the write the log file all at once, and so can't automatically translate the start tag and end + * tag for this element. + */ + @simpl_collection + @simpl_scope(MIXED_INITIATIVE_OP_TRANSLATION_SCOPE) + protected ArrayList opSequence; + + Thread thread; + + /** + * Does all the work of logging, if there is any work to be done. If this is null, then there is + * no logging; conversely, if there is no logging, this is null. + */ + ArrayList logWriters = null; + + /** + * This is the Vector for the operations that are being queued up before they can go to + * outgoingOps. + */ + private StringBuilder incomingOpsBuffer; + + /** + * This is the Vector for the operations that are in the process of being written out. + */ + private StringBuilder outgoingOpsBuffer; + + /** Stores the pointer to outgoingOpsBuffer for swapQueues. */ + private StringBuilder tempOpsBuffer; + + static final int THREAD_PRIORITY = 1; + + /** Amount of time for writer thread to sleep; 15 seconds */ + static final int SLEEP_TIME = 15000; + + static final long sessionStartTime = System.currentTimeMillis(); + + long lastGcTime; + + /** Amount of time to wait before booting the garbage collector; 5 minutes */ + static final long KICK_GC_INTERVAL = 300000; + + private static final String SESSION_LOG_START = "\n\n "; + + static final String OP_SEQUENCE_START = "\n\n\n\n"; + + static final String OP_SEQUENCE_END = "\n\n"; + + /** Logging closing message string written to the logging file at the end */ + public static final String LOG_CLOSING = "\n\n\n"; + + /** Logging Header message string written to the logging file in the begining */ + static final String BEGIN_EMIT = XMLTools.xmlHeader() + + SESSION_LOG_START; + + /** Preference setting for no logging. */ + public static final int NO_LOGGING = 0; + + /** Preference setting for logging to a file using normal IO. */ + public static final int LOG_TO_FILE = 1; + + /** Preference setting for logging to a remote server. */ + public static final int LOG_TO_SERVICES_SERVER = 2; + + /** Preference setting for logging to a file using memory-mapped IO. */ + public static final int LOG_TO_MEMORY_MAPPED_FILE = 4; + + /** Preference setting for logging both to a memory-mapped file and a server. */ + public static final int LOG_TO_MM_FILE_AND_SERVER_REDUNDANT = LOG_TO_MEMORY_MAPPED_FILE + & LOG_TO_SERVICES_SERVER; + + /** Preference setting for logging both to a normal IO file and a server. */ + public static final int LOG_TO_FILE_AND_SERVER_REDUNDANT = LOG_TO_FILE + & LOG_TO_SERVICES_SERVER; + + static final int MAX_OPS_BEFORE_WRITE = 10; + + public static final String LOGGING_HOST_PARAM = "logging_host"; + + public static final String LOGGING_PORT_PARAM = "logging_port"; + + public static final String LOGGING_MODE_PARAM = "log_mode"; + + final int maxOpsBeforeWrite; + + final int maxBufferSizeToWrite; + + /** used to prevent writes from getting interrupt()'ed */ + private Object threadSemaphore = new Object(); + + private volatile boolean runMethodDone = false; + + volatile boolean finished; + + private boolean running = false; + + /** + * Instantiates a Logging object based on the given log file name. This constructor assumes that a + * set of loaded {@link ecologylab.appframework.types.prefs.Pref Pref}s will handle other + * settings, indicating how logging will be performed, and the server setup (if logging over a + * network). + */ + public Logging(String logFileName) + { + this(logFileName, MAX_OPS_BEFORE_WRITE); + } + + /** + * Instantiates a Logging object based on the given log file name and the maximum operations + * before write. This constructor assumes that a set of loaded + * {@link ecologylab.appframework.types.prefs.Pref Pref}s will handle other settings, indicating + * how logging will be performed, and the server setup (if logging over a network). + */ + public Logging(String logFileName, int maxOpsBeforeWrite) + { + this( logFileName, + false, + maxOpsBeforeWrite, + Pref.lookupInt(LOGGING_MODE_PARAM, NO_LOGGING), + Pref.lookupString(LOGGING_HOST_PARAM, "localhost"), + Pref.lookupInt(LOGGING_PORT_PARAM, ServicesHostsAndPorts.LOGGING_PORT), + null); + } + + /** + * Instantiates a Logging object based on the supplied parameters. This constructor does not rely + * on {@link ecologylab.appframework.types.prefs.Pref Pref}s. + * + * @param logFileName + * the name of the file to which the log will be written. + * @param logFileNameAbsolute + * TODO + * @param maxOpsBeforeWrite + * the maximum number of ops to record in memory before writing them to the set media. + * @param logMode + * the media to which the logger will write, such as a memory-mapped file or a server. + * @param loggingHost + * the host to which to log if using networked logging (may be null if local logging is + * desired). + * @param loggingPort + * the port of the host to which to log if using networked logging (may be 0 if local + * logging is desired). + * @deprecated Use {@link #Logging(String,boolean,int,int,String,int,ApplicationEnvironment)} + * instead + */ + @Deprecated + public Logging( String logFileName, + boolean logFileNameAbsolute, + int maxOpsBeforeWrite, + int logMode, + String loggingHost, + int loggingPort) + { + this( logFileName, + logFileNameAbsolute, + maxOpsBeforeWrite, + logMode, + loggingHost, + loggingPort, + null); + } + + /** + * Instantiates a Logging object based on the supplied parameters. This constructor does not rely + * on {@link ecologylab.appframework.types.prefs.Pref Pref}s. + * + * @param logFileName + * the name of the file to which the log will be written. + * @param logFileNameAbsolute + * TODO + * @param maxOpsBeforeWrite + * the maximum number of ops to record in memory before writing them to the set media. + * @param logMode + * the media to which the logger will write, such as a memory-mapped file or a server. + * @param loggingHost + * the host to which to log if using networked logging (may be null if local logging is + * desired). + * @param loggingPort + * the port of the host to which to log if using networked logging (may be 0 if local + * logging is desired). + * @param environment + * TODO + */ + public Logging( String logFileName, + boolean logFileNameAbsolute, + int maxOpsBeforeWrite, + int logMode, + String loggingHost, + int loggingPort, + ApplicationEnvironment environment) + { + this(maxOpsBeforeWrite); + + if (logMode == NO_LOGGING) + { + debug("logging disabled; NO_LOGGING specified"); + } + else + { + logWriters = new ArrayList(1); + + if ((logMode & LOG_TO_FILE) == LOG_TO_FILE) + { + if (logFileName == null) + { + debug("Logging disabled; no file name specified"); + } + else + { + File logDir; + if (!logFileNameAbsolute) + { + if (environment == null) + logDir = PropertiesAndDirectories.logDir(); + else + logDir = PropertiesAndDirectories.logDir(environment); + } + else + { + logDir = new File(logFileName); + } + + if (logDir == null) + { + debug("Can't write to logDir=" + logDir); + } + else + { + File logFile; + + if (!logFileNameAbsolute) + { + logFile = new File(logDir, logFileName); + } + else + { + logFile = logDir; + } + debug("Logging to file: " + logFile.getAbsolutePath()); + + try + { + XMLTools.createParentDirs(logFile); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + + BufferedWriter bufferedWriter = Files.openWriter(logFile); + + if (bufferedWriter != null) + { + try + { + logWriters.add(new FileLogWriter(logFile, bufferedWriter)); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + else + { + debug("ERROR: cant open writer to " + logFile); + } + } + } + } + + if ((logMode & LOG_TO_MEMORY_MAPPED_FILE) == LOG_TO_MEMORY_MAPPED_FILE) + { + if (logFileName == null) + { + debug("Logging disabled; no file name specified"); + } + else + { + File logDir; + if (!logFileNameAbsolute) + { + logDir = PropertiesAndDirectories.logDir(); + } + else + { + logDir = new File(logFileName); + } + + if (logDir == null) + { + debug("Can't write to logDir=" + logDir); + } + else + { + File logFile; + + if (!logFileNameAbsolute) + { + logFile = new File(logDir, logFileName); + } + else + { + logFile = logDir; + } + + try + { + XMLTools.createParentDirs(logFile); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + debug("Logging to file: " + logFile.getAbsolutePath()); + + try + { + logWriters.add(new MemoryMappedFileLogWriter(logFile)); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + } + if ((logMode & LOG_TO_SERVICES_SERVER) == LOG_TO_SERVICES_SERVER) + { + /** + * Create the logging client which communicates with the logging server + */ + if (loggingHost == null) + loggingHost = LOGGING_HOST; + + NIOClient loggingClient = null; + try + { + loggingClient = new NIOClient(loggingHost, + loggingPort, + DefaultServicesTranslations.get(), + new Scope()); + + // CONNECT TO SERVER + if (loggingClient.connect()) + { + logWriters.add(new NetworkLogWriter(loggingClient, this)); + + debug("logging to server: " + loggingHost + ":" + loggingPort); + } + else + { + loggingClient = null; + debug("Logging disabled: cannot reach server"); + } + } + catch (IOException e1) + { + e1.printStackTrace(); + } + + debug("**************************************************************connecting to server."); + + } + } + } + + /** + * Constructor for automatic translation from XML + * + */ + public Logging() + { + this(MAX_OPS_BEFORE_WRITE); + } + + protected Logging(int maxOpsBeforeWrite) + { + this.maxOpsBeforeWrite = maxOpsBeforeWrite; + final int maxBufferSizeToWrite = maxOpsBeforeWrite * 1024; + incomingOpsBuffer = new StringBuilder(maxBufferSizeToWrite); + outgoingOpsBuffer = new StringBuilder(maxBufferSizeToWrite); + this.maxBufferSizeToWrite = maxBufferSizeToWrite; + } + + private void swapBuffers() + { + synchronized (outgoingOpsBuffer) + { + synchronized (incomingOpsBuffer) + { + if (outgoingOpsBuffer.length() == 0) + { + tempOpsBuffer = outgoingOpsBuffer; + outgoingOpsBuffer = incomingOpsBuffer; + incomingOpsBuffer = tempOpsBuffer; + } + } + } + } + + /** + * Translates op to XML then logs it, if this Logging object is running. Returns true if the + * operation was placed in the buffer to be written, false if it failed (because the op could not + * be translated to XML). + * + * @param op + * - the operation to be logged. + */ + public boolean logAction(MixedInitiativeOp op) + { + if (!this.finished && logWriters != null) + { + try + { + synchronized (incomingOpsBuffer) + { + SimplTypesScope.serialize(op, incomingOpsBuffer, StringFormat.XML); + } + + // final int bufferLength = incomingOpsBuffer.length(); + // if ((thread != null) && (bufferLength > maxBufferSizeToWrite)) + // { + // synchronized (threadSemaphore) + // { + // debugA("interrupting thread to do i/o now: " + bufferLength + // + "/" + maxBufferSizeToWrite); + // thread.interrupt(); + // // end sleep in that thread prematurely to do i/o + // } + // } + + return true; + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + } + + return false; + } + + /** + * Returns the size of the list of log ops. May not be the correct value if called during logging. + * This method should only be used for playback purposes. + * + * @return the size of opSequence. + */ + public int size() + { + return this.opSequence.size(); + } + + /** + * Write the start of the log header out to the log file OR, send the begining logging file + * message so that logging server write the start of the log header. + *

+ * Then start the looping thread that periodically wakes up and performs log i/o. + */ + @Override + public void start() + { + debug("Logging starting up..."); + if ((logWriters != null) && (thread == null)) + { + thread = new Thread(this); + thread.setPriority(THREAD_PRIORITY); + thread.start(); + + this.running = true; + } + } + + /** + * Finishes writing any queued actions, then sends the epilogue; then shuts down. + * + */ + @Override + public synchronized void stop() + { + debug("shutting down..."); + + if (!finished && thread != null) + { + finished = true; + + debug("initiating shutdown sequence..."); + + int timesToWait = 100; + + while (!this.runMethodDone && timesToWait-- > 0) + { + debug("waiting on run method to finish log writing (attempts remaining " + timesToWait + + ")..."); + thread.interrupt(); + Generic.sleep(500); + } + + if (timesToWait == 0) + { + debug("...giving up on waiting for run thread; continuing shutdown."); + } + else + { + debug("...done."); + } + + this.thread = null; + + synchronized (threadSemaphore) + { // since we only write from run() if we're low on memory, we may + // have all the ops still unwritten. + writeBufferedOps(); + } + + if (logWriters != null) + { + final Epilogue epilogue = getEpilogue(); + // necessary for acquiring wrapper characters, like + final SendEpilogue sendEpilogue = new SendEpilogue(this, epilogue); + + for (LogWriter logWriter : logWriters) + { + logWriter.setPriority(9); + debug("stop() writing epilogue to " + logWriter); + logWriter.writeLogMessage(sendEpilogue); + } + + // try + // { + // debug("epilogue contents: " + sendEpilogue.serialize()); + // } + // catch (SIMPLTranslationException e) + // { + // e.printStackTrace(); + // } + + synchronized (threadSemaphore) + { + debug("forcing final write"); + writeBufferedOps(); + } + + for (LogWriter logWriter : logWriters) + { + debug("stop() closing " + logWriter); + logWriter.close(); + } + + debug("...stop() finished."); + + logWriters = null; + } + } + debug("...shutdown complete."); + + this.running = false; + } + + /** + * Logging to a file is delayed to the actions of this thread, because otherwise, it can mess up + * priorities in the system, because events get logged in the highest priority thread. + *

+ * This MUST be the only thread that ever calls writeQueuedActions(). + */ + @Override + public void run() + { + this.runMethodDone = false; + this.finished = false; + + final Prologue prologue = getPrologue(); + String uid = Pref.lookupString("uid", "0"); + Logging.this.debug("Logging: Sending Prologue userID:" + uid); + prologue.setUserID(uid); + + // necessary for acquiring wrapper characters, like + final SendPrologue sendPrologue = new SendPrologue(Logging.this, prologue); + + for (LogWriter logWriter : logWriters) + { + debug("sending prologue"); + logWriter.writeLogMessage(sendPrologue); + } + + lastGcTime = System.currentTimeMillis(); + while (!finished) + { + Thread.interrupted(); + Generic.sleep(SLEEP_TIME, false); + + if (finished) + debug("run thread awakened for final run"); + + if (!Memory.reclaimIfLow()) + { + synchronized (threadSemaphore) + { + writeBufferedOps(); + } + } + + if (finished) + debug("run thread finishing"); + } + + debug("run thread finished."); + // now that we are finished, we let everyone else know + this.runMethodDone = true; + } + + /** + * Use the LogWriter, if there is one, to output queued actions to the log. + *

+ * NB: This method is SINGLE Threaded! It is not thread safe. It must only be called from the + * run() method. + */ + protected void writeBufferedOps() + { + StringBuilder bufferToWrite = incomingOpsBuffer; + synchronized (bufferToWrite) + { + int size = bufferToWrite.length(); + + if (size == 0) + return; + swapBuffers(); + // what was incomingOps is now outgoing! + if (logWriters != null) + { + for (LogWriter logWriter : logWriters) + { + logWriter.writeBufferedOps(bufferToWrite); + } + } + // debug("Logging: writeQueuedActions() after output loop."); + bufferToWrite.setLength(0); + } + } + + /** + * A message at the beginnging of the log. This method may be overridden to return a subclass of + * Prologue, by subclasses of this, that wish to emit application specific information at the + * start of a log. + * + * @return + */ + public Prologue getPrologue() + { + return new Prologue(); + } + + /** + * A message at the end of the log. This method may be overridden to return a subclass of + * Epilogue, by subclasses of this, that wish to emit application specific information at the end + * of a log. + * + * @return + */ + protected Epilogue getEpilogue() + { + Epilogue epilogue = new Epilogue(); + return epilogue; + } + + /** + * Return our session start timestamp. + * + * @return + */ + public static final long sessionStartTime() + { + return sessionStartTime; + } + + /** + * Objects that process queuedActions for writing, either to a local file, or, using the network, + * to the LoggingServer. + * + * @author andruid + * @author Zachary O. Toups (zach@ecologylab.net) + */ + protected abstract class LogWriter extends Debug + { + LogWriter() throws IOException + { + + } + + /** + * Get the bufferToLog() from the LogRequestMessage. Write it out! + * + * @param logRequestMessage + */ + void writeLogMessage(LogEvent logRequestMessage) + { + StringBuilder buffy = logRequestMessage.bufferToLog(); + writeLogMessage(buffy); + + } + + abstract void writeLogMessage(StringBuilder xmlBuffy); + + void writeBufferedOps(StringBuilder opsBuffer) + { + writeLogMessage(opsBuffer); + } + + abstract void close(); + + public void setPriority(int priority) + { + + } + } + + /** + * LogWriter that uses a memory-mapped local file for logging. + * + * @author andruid + * @author Zachary O. Toups (zach@ecologylab.net) + */ + protected class MemoryMappedFileLogWriter extends LogWriter + { + // BufferedWriter bufferedWriter; + MappedByteBuffer buffy = null; + + FileChannel channel = null; + + private CharsetEncoder encoder = Charset.forName(NetworkingConstants.CHARACTER_ENCODING) + .newEncoder(); + + private File logFile; + + /** + * The base size for the log file, and the amount it will be incremented whenever its buffer + * overflows. + */ + static final int LOG_FILE_INCREMENT = 1024 * 512; + + private int endOfMappedBytes = LOG_FILE_INCREMENT; + + MemoryMappedFileLogWriter(File logFile) throws IOException + { + this.logFile = logFile; + + channel = new RandomAccessFile(logFile, "rw").getChannel(); + + // allocate LOG_FILE_INCREMENT for the file size; this will be + // incremented as necessary + buffy = channel.map(MapMode.READ_WRITE, 0, LOG_FILE_INCREMENT); + + // if (bufferedWriter == null) + // throw new IOException("Can't log to File with null + // buffereredWriter."); + // this.bufferedWriter = bufferedWriter; + Logging.this.debugA("Logging to " + logFile + " " + buffy); + } + + /** + * Get the bufferToLog() from the LogRequestMessage. Write it out! + * + * @param buffer + */ + @Override + void writeLogMessage(StringBuilder buffer) + { + try + { + putInBuffer(encoder.encode(CharBuffer.wrap(buffer))); + } + catch (CharacterCodingException e) + { + e.printStackTrace(); + } + + } + + @Override + public void close() + { + try + { + buffy.force(); + + // shrink the file to the appropriate size + int fileSize = 0; + + fileSize = endOfMappedBytes - LOG_FILE_INCREMENT + buffy.position(); + + buffy = null; + + channel.close(); + + channel = null; + + // do garbage collection to ensure that the file is no longer + // mapped + System.runFinalization(); + System.gc(); + + debug("final log file size is " + fileSize + " bytes."); + + debug("truncating log."); + + boolean truncated = false; + int numTries = 0; + + while (!truncated) + { + try + { + new RandomAccessFile(logFile, "rw").getChannel().truncate(fileSize); + + truncated = true; + } + catch (IOException e) + { + debug("truncation failed because the file is still mapped, attempting to garbage collect...AGAIN."); + + // do garbage collection to ensure that the file is no + // longer mapped + System.runFinalization(); + System.gc(); + + numTries++; + } + + if (numTries == 100) + { + debug("Tried to unmap file 100 times; failing now."); + + truncated = true; + } + } + } + catch (IOException e1) + { + e1.printStackTrace(); + } + } + + private void putInBuffer(ByteBuffer incoming) + { + + try + { + int remaining = buffy.remaining(); + + if (remaining < incoming.remaining()) + { // we want to write more than will fit; so we just write + // what we can first... + debug("not enough space in the buffer: " + remaining + "/" + + incoming.remaining() + "; old range: " + (endOfMappedBytes - LOG_FILE_INCREMENT) + "-" + + endOfMappedBytes+"; new range: " + (endOfMappedBytes) + "-" + + (endOfMappedBytes + LOG_FILE_INCREMENT)); + + byte[] temp = new byte[remaining]; + incoming.get(temp, 0, remaining); + + buffy.put(temp); + + // ensure that the buffer has been written out + buffy.force(); + + // then shift buffy to map to the next segment of the file + buffy = channel.map(MapMode.READ_WRITE, endOfMappedBytes, LOG_FILE_INCREMENT); + endOfMappedBytes += LOG_FILE_INCREMENT; + + // recursively call on the remainder of incoming + putInBuffer(incoming); + } + else + { + if (show(5)) + debug("writing to buffer: " + remaining + "bytes remaining before resize"); + + buffy.put(incoming); + } + } + catch (NullPointerException e) + { + debug("null pointer; data to be written:"); + try + { + debug(Charset.forName("ASCII").newDecoder().decode(incoming).toString()); + } + catch (CharacterCodingException e1) + { + e1.printStackTrace(); + } + + e.printStackTrace(); + } + catch (CharacterCodingException e) + { + e.printStackTrace(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + + /** + * LogWriter that uses a local file for logging. + * + * @author andruid + * @author Zachary O. Toups (zach@ecologylab.net) + */ + protected class FileLogWriter extends LogWriter + { + BufferedWriter bufferedWriter; + + FileLogWriter(File logFile, BufferedWriter bufferedWriter) throws IOException + { + if (bufferedWriter == null) + throw new IOException("Can't log to File with null buffereredWriter."); + this.bufferedWriter = bufferedWriter; + Logging.this.debugA("Logging to " + logFile + " " + bufferedWriter); + } + + /** + * Write the opsBuffer to a file. + */ + @Override + void writeLogMessage(StringBuilder buffy) + { + try + { + bufferedWriter.append(buffy); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + @Override + void close() + { + try + { + bufferedWriter.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + bufferedWriter = null; + } + } + + /** + * LogWriter that connects to the ServicesServer over the network for logging. + * + * @author andruid + * @author Zachary O. Toups (zach@ecologylab.net) + */ + protected class NetworkLogWriter extends LogWriter + { + NIOClient loggingClient; + + /** Object for sending a batch of ops to the LoggingServer. */ + final LogOps logOps; + + /** + * The owner of this Logging object, used to ensure that, during shutdown, this object blocks + * until it is finished sending; needed to determine the current status. + */ + final Logging loggingParent; + + NetworkLogWriter(NIOClient loggingClient, Logging loggingParent) throws IOException + { + if (loggingClient == null) + throw new IOException("Can't log to Network with null loggingClient."); + this.loggingClient = loggingClient; + Logging.this.debug("Logging to service via connection: " + loggingClient); + + // logOps = new LogOps(maxBufferSizeToWrite); + logOps = new LogOps(); + + this.loggingParent = loggingParent; + } + + @Override + public void setPriority(int priority) + { + NIOClient loggingClient = this.loggingClient; + if (loggingClient != null) + loggingClient.setPriority(priority); + } + + /** + * Writes the given message to the logging server. Recursively calls itself if the message is + * too large to send at once. + */ + @Override + void writeLogMessage(LogEvent message) + { + try + { + if (!this.loggingParent.finished) + { + debug(">> sending a normal log message (non-blocking): "); + try + { + debug(SimplTypesScope.serialize(message, StringFormat.XML).toString()); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + loggingClient.nonBlockingSendMessage(message); + } + else + { + // finishing, wait 50 seconds + int timeOutMillis = 50000; + + debug(">> network logging finishing, waiting up to " + (timeOutMillis / 1000) + + " seconds..."); + + ResponseMessage rm = loggingClient.sendMessage(message, timeOutMillis); + + if (rm == null) + debug("!!! gave up waiting for server response after " + (timeOutMillis / 1000) + + " seconds."); + else + debug(">>> final log ops sent successfully!"); + } + } + catch (IOException e) + { + e.printStackTrace(); + } + catch (MessageTooLargeException e) + { + StringBuilder bufferToLog = message.bufferToLog(); + int half = bufferToLog.length() / 2; + + warning("!!!! attempted to send a message that was too large, splitting in half and trying again recursively (" + + bufferToLog.length() + "/2 == " + half + ")"); + + LogOps firstHalf = new LogOps(); + firstHalf.setBuffer(new StringBuilder(bufferToLog.subSequence(0, half))); + + LogOps secondHalf = new LogOps(); + secondHalf.setBuffer(new StringBuilder(bufferToLog.subSequence(half, bufferToLog.length()))); + + this.writeLogMessage(firstHalf); + this.writeLogMessage(secondHalf); + + // if (message instanceof SendPrologue) + // { // if this is a send prologue, send prologue has to happen first + // message.setBuffer(new StringBuilder(bufferToLog.subSequence(0, half))); + // this.writeLogMessage(message); + // } + // else + // { + // this.writeBufferedOps(new StringBuilder(bufferToLog.subSequence(0, half))); + // } + // + // if (message instanceof SendEpilogue) + // { // if this is a send epilogue, send epilogue has to happen last + // message.setBuffer(new StringBuilder(bufferToLog.subSequence(half, + // bufferToLog.length()))); + // this.writeLogMessage(message); + // } + // else + // { + // this.writeBufferedOps(new StringBuilder(bufferToLog.subSequence(half, bufferToLog + // .length()))); + // } + } + } + + @Override + void writeBufferedOps(StringBuilder buffy) + { + logOps.setBuffer(buffy); + + writeLogMessage(logOps); + + logOps.clear(); + buffy.setLength(0); + } + + /** + * Close the connection to the loggingServer. + */ + @Override + void close() + { + debug("close."); + + loggingClient.disconnect(); + loggingClient = null; + } + + @Override + void writeLogMessage(StringBuilder xmlBuffy) + { + throw new UnsupportedOperationException(); + } + } + + /** + * @return the opSequence + */ + public ArrayList getOpSequence() + { + return opSequence; + } + + /** + * @return the running + */ + public boolean isRunning() + { + return running; + } +} diff --git a/simplCore/src/ecologylab/oodss/logging/LoggingClientSessionManager.java b/simplCore/src/ecologylab/oodss/logging/LoggingClientSessionManager.java index 69e31624..57870f84 100644 --- a/simplCore/src/ecologylab/oodss/logging/LoggingClientSessionManager.java +++ b/simplCore/src/ecologylab/oodss/logging/LoggingClientSessionManager.java @@ -1,74 +1,74 @@ -/** - * - */ -package ecologylab.oodss.logging; - -import java.nio.channels.SelectionKey; - -import ecologylab.collections.Scope; -import ecologylab.oodss.distributed.impl.NIOServerIOThread; -import ecologylab.oodss.distributed.server.clientsessionmanager.ClientSessionManager; -import ecologylab.serialization.SimplTypesScope; - -/** - * Provides a special implementation of performService(), that open()'s an OutputStream as necessary - * to the appropriate directory for logging, based on the headers in the message, then logs the - * message to there with a minimum of translation. - * - * @author andruid - * @author eunyee - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class LoggingClientSessionManager extends ClientSessionManager, Scope> -{ - boolean end = false; - - /** - * @param token - * @param loggingServer - * @param server - * @param socket - * @param translationScope - * @param appObjScope - */ - public LoggingClientSessionManager(String sessionId, int maxPacketSize, - NIOLoggingServer loggingServer, NIOServerIOThread server, SelectionKey sk, - SimplTypesScope translationScope, Scope appObjScope) - { - super(sessionId, maxPacketSize, server, loggingServer, sk, translationScope, appObjScope); - } - - @Override - public void shutdown() - { - while (this.messageWaiting || this.requestQueue.size() > 0) - { - try - { - wait(100); - } - catch (InterruptedException e) - { - e.printStackTrace(); - } - } - - if (this.localScope.getOutputStreamWriter() != null) - { // if the local scope still contains the output stream, then shutdown isn't complete! - // this will make the log readable, but it will not have its real epilogue - SendEpilogue sE = new SendEpilogue(); - sE.performService(localScope); - } - - super.shutdown(); - } - - /** - * @see ecologylab.oodss.distributed.server.clientsessionmanager.BaseSessionManager#generateContextScope(ecologylab.collections.Scope) - */ - @Override - protected LoggingContextScope generateContextScope(Scope baseScope) - { - return new LoggingContextScope(baseScope); - } -} +/** + * + */ +package ecologylab.oodss.logging; + +import java.nio.channels.SelectionKey; + +import ecologylab.collections.Scope; +import ecologylab.oodss.distributed.impl.NIOServerIOThread; +import ecologylab.oodss.distributed.server.clientsessionmanager.ClientSessionManager; +import ecologylab.serialization.SimplTypesScope; + +/** + * Provides a special implementation of performService(), that open()'s an OutputStream as necessary + * to the appropriate directory for logging, based on the headers in the message, then logs the + * message to there with a minimum of translation. + * + * @author andruid + * @author eunyee + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class LoggingClientSessionManager extends ClientSessionManager, Scope> +{ + boolean end = false; + + /** + * @param token + * @param loggingServer + * @param server + * @param socket + * @param translationScope + * @param appObjScope + */ + public LoggingClientSessionManager(String sessionId, int maxPacketSize, + NIOLoggingServer loggingServer, NIOServerIOThread server, SelectionKey sk, + SimplTypesScope translationScope, Scope appObjScope) + { + super(sessionId, maxPacketSize, server, loggingServer, sk, translationScope, appObjScope); + } + + @Override + public void shutdown() + { + while (this.messageWaiting || this.requestQueue.size() > 0) + { + try + { + wait(100); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + + if (this.localScope.getOutputStreamWriter() != null) + { // if the local scope still contains the output stream, then shutdown isn't complete! + // this will make the log readable, but it will not have its real epilogue + SendEpilogue sE = new SendEpilogue(); + sE.performService(localScope); + } + + super.shutdown(); + } + + /** + * @see ecologylab.oodss.distributed.server.clientsessionmanager.BaseSessionManager#generateContextScope(ecologylab.collections.Scope) + */ + @Override + protected LoggingContextScope generateContextScope(Scope baseScope) + { + return new LoggingContextScope(baseScope); + } +} diff --git a/simplCore/src/ecologylab/oodss/logging/LoggingContextScope.java b/simplCore/src/ecologylab/oodss/logging/LoggingContextScope.java index 7974b54b..07785494 100644 --- a/simplCore/src/ecologylab/oodss/logging/LoggingContextScope.java +++ b/simplCore/src/ecologylab/oodss/logging/LoggingContextScope.java @@ -1,108 +1,108 @@ -/** - * - */ -package ecologylab.oodss.logging; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetEncoder; -import java.util.Map; - -import ecologylab.collections.Scope; -import ecologylab.generic.Debug; -import ecologylab.oodss.distributed.common.NetworkingConstants; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class LoggingContextScope extends Scope -{ - protected Writer outputStreamWriter; - - public LoggingContextScope(Map parent) - { - super(parent); - } - - public synchronized void setUpOutputStreamWriter(String logFileName) throws IOException - { - String logFilesPath = (String) this.get(NIOLoggingServer.LOG_FILES_PATH); - - String fileName = logFilesPath + logFileName; - - File file = new File(fileName); - String dirPath = file.getParent(); - if (dirPath != null) - { - Debug.println("dirPath = " + dirPath); - - File dir = new File(dirPath); - if (!dir.exists()) - { - Debug.println("dirPath did not exist. create with mkdirs()"); - dir.mkdirs(); - } - } - - Debug.println("attempting to use filename: " + fileName); - // rename file until we are not overwriting an existing file - if (file.exists()) - { // a little weird to do it this way, but the if is cheaper than - // potentially reallocating the String over and over - String filename = file.getName(); - int dotIndex = filename.lastIndexOf('.'); - int i = 1; - - do - { - Debug.println(filename + " already exists."); - - String newFilename = (dotIndex > -1 ? filename.substring(0, dotIndex) - + i - + filename.substring(dotIndex) : filename + i); - Debug.println("trying new filename = " + newFilename); - i++; - - // we already took care of the parent directories - // just need to make a new file w/ a new name - file = new File(newFilename); - } - while (file.exists()); - } - - if (!file.createNewFile()) - { - throw new IOException("Could not create the logging file."); - } - - Debug.println("Logging to file at: " + file.getAbsolutePath()); - - FileOutputStream fos = new FileOutputStream(file, true); - CharsetEncoder encoder = Charset.forName(NetworkingConstants.CHARACTER_ENCODING).newEncoder(); - - outputStreamWriter = new OutputStreamWriter(fos, encoder); - } - - /** - * @return the outputStreamWriter - */ - public Writer getOutputStreamWriter() - { - return outputStreamWriter; - } - - /** - * Sets outputStreamWriter to null so that logging server can try to shut down. - * - * TODO Should handle semantics of shutting down output stream. - */ - public synchronized void shutdown() - { - this.outputStreamWriter = null; - } -} +/** + * + */ +package ecologylab.oodss.logging; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.util.Map; + +import ecologylab.collections.Scope; +import ecologylab.generic.Debug; +import ecologylab.oodss.distributed.common.NetworkingConstants; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class LoggingContextScope extends Scope +{ + protected Writer outputStreamWriter; + + public LoggingContextScope(Map parent) + { + super(parent); + } + + public synchronized void setUpOutputStreamWriter(String logFileName) throws IOException + { + String logFilesPath = (String) this.get(NIOLoggingServer.LOG_FILES_PATH); + + String fileName = logFilesPath + logFileName; + + File file = new File(fileName); + String dirPath = file.getParent(); + if (dirPath != null) + { + Debug.println("dirPath = " + dirPath); + + File dir = new File(dirPath); + if (!dir.exists()) + { + Debug.println("dirPath did not exist. create with mkdirs()"); + dir.mkdirs(); + } + } + + Debug.println("attempting to use filename: " + fileName); + // rename file until we are not overwriting an existing file + if (file.exists()) + { // a little weird to do it this way, but the if is cheaper than + // potentially reallocating the String over and over + String filename = file.getName(); + int dotIndex = filename.lastIndexOf('.'); + int i = 1; + + do + { + Debug.println(filename + " already exists."); + + String newFilename = (dotIndex > -1 ? filename.substring(0, dotIndex) + + i + + filename.substring(dotIndex) : filename + i); + Debug.println("trying new filename = " + newFilename); + i++; + + // we already took care of the parent directories + // just need to make a new file w/ a new name + file = new File(newFilename); + } + while (file.exists()); + } + + if (!file.createNewFile()) + { + throw new IOException("Could not create the logging file."); + } + + Debug.println("Logging to file at: " + file.getAbsolutePath()); + + FileOutputStream fos = new FileOutputStream(file, true); + CharsetEncoder encoder = Charset.forName(NetworkingConstants.CHARACTER_ENCODING).newEncoder(); + + outputStreamWriter = new OutputStreamWriter(fos, encoder); + } + + /** + * @return the outputStreamWriter + */ + public Writer getOutputStreamWriter() + { + return outputStreamWriter; + } + + /** + * Sets outputStreamWriter to null so that logging server can try to shut down. + * + * TODO Should handle semantics of shutting down output stream. + */ + public synchronized void shutdown() + { + this.outputStreamWriter = null; + } +} diff --git a/simplCore/src/ecologylab/oodss/logging/LogueMessage.java b/simplCore/src/ecologylab/oodss/logging/LogueMessage.java index 8f277cc2..2c6103ca 100644 --- a/simplCore/src/ecologylab/oodss/logging/LogueMessage.java +++ b/simplCore/src/ecologylab/oodss/logging/LogueMessage.java @@ -1,40 +1,40 @@ -package ecologylab.oodss.logging; - -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Base class for SendPrologue and SendEpilogue. Probably should not be used for anything else. Enables passing of the - * logName, in order to write custom log XML element open and close tags. - * - * @author andruid - */ -@simpl_inherit abstract public class LogueMessage extends LogEvent -{ - @simpl_scalar protected String logName; - - /** - * Constructor for building from the Logging class. - * - * @param logging - */ - public LogueMessage(Logging logging) - { - logName = XMLTools.getXmlTagName(logging.getClass(), "State"); - } - - /** - * Constructor for automatic translation; - */ - public LogueMessage() - { - super(); - } - - public String logName() - { - return (logName != null) ? logName : "logging"; - } - -} +package ecologylab.oodss.logging; + +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Base class for SendPrologue and SendEpilogue. Probably should not be used for anything else. Enables passing of the + * logName, in order to write custom log XML element open and close tags. + * + * @author andruid + */ +@simpl_inherit abstract public class LogueMessage extends LogEvent +{ + @simpl_scalar protected String logName; + + /** + * Constructor for building from the Logging class. + * + * @param logging + */ + public LogueMessage(Logging logging) + { + logName = XMLTools.getXmlTagName(logging.getClass(), "State"); + } + + /** + * Constructor for automatic translation; + */ + public LogueMessage() + { + super(); + } + + public String logName() + { + return (logName != null) ? logName : "logging"; + } + +} diff --git a/simplCore/src/ecologylab/oodss/logging/MixedInitiativeOp.java b/simplCore/src/ecologylab/oodss/logging/MixedInitiativeOp.java index bccc6851..1b7ba77b 100644 --- a/simplCore/src/ecologylab/oodss/logging/MixedInitiativeOp.java +++ b/simplCore/src/ecologylab/oodss/logging/MixedInitiativeOp.java @@ -1,76 +1,76 @@ -package ecologylab.oodss.logging; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * A user operation, which can be serialized, logged, Undo/Redo'ed, played in history, and so on. - * - * @author andruid - */ -@simpl_inherit -abstract public class MixedInitiativeOp extends BasicOp -{ - @simpl_scalar protected short intensity; - - /** - * invert value for the dual operation. - * This value indicates which operation should be performed in the object of dual operations. - */ - @simpl_scalar protected boolean invert; - - @simpl_scalar protected String action = null; - @simpl_scalar protected long recordTime; - - static protected final short UNKNOWN_OP = -1024; - static protected final short UNDEFINED_OP = -1; - static protected final short AGENT_OP = 0; - static protected final short HUMAN_ELEMENT_OP = 1; - static protected final short HUMAN_EDIT_OP = 2; - static protected final short CONTROL_OP = 3; - static protected final short PROGRAM_OP = 4; - - /** No-argument constructor for XML translation. */ - public MixedInitiativeOp() - { - super(); - } - - /** - * Perform the op. Perhaps invert it, as for undo. - * - * @param invert - */ - abstract public void performAction(boolean invert); - - /** - * In a mixed initiative system, some ops are by the human, while others are by the agent. - * - * The presence of this here at the moment may be a hack. It may be good design :-) Human and dyadic undo should - * probably be split into 2 separte UndoRedo classes. - * - * @return - */ - public boolean isHuman(){ - return true; - } - - public long recordTime() - { - return recordTime; - } - - public void setRecordTime(long recordTime) { - this.recordTime = recordTime; - } - - /** Free resources associated with this. */ - @Override - public void recycle(boolean invert){} - - public String action() - { - return action; - } - -} +package ecologylab.oodss.logging; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * A user operation, which can be serialized, logged, Undo/Redo'ed, played in history, and so on. + * + * @author andruid + */ +@simpl_inherit +abstract public class MixedInitiativeOp extends BasicOp +{ + @simpl_scalar protected short intensity; + + /** + * invert value for the dual operation. + * This value indicates which operation should be performed in the object of dual operations. + */ + @simpl_scalar protected boolean invert; + + @simpl_scalar protected String action = null; + @simpl_scalar protected long recordTime; + + static protected final short UNKNOWN_OP = -1024; + static protected final short UNDEFINED_OP = -1; + static protected final short AGENT_OP = 0; + static protected final short HUMAN_ELEMENT_OP = 1; + static protected final short HUMAN_EDIT_OP = 2; + static protected final short CONTROL_OP = 3; + static protected final short PROGRAM_OP = 4; + + /** No-argument constructor for XML translation. */ + public MixedInitiativeOp() + { + super(); + } + + /** + * Perform the op. Perhaps invert it, as for undo. + * + * @param invert + */ + abstract public void performAction(boolean invert); + + /** + * In a mixed initiative system, some ops are by the human, while others are by the agent. + * + * The presence of this here at the moment may be a hack. It may be good design :-) Human and dyadic undo should + * probably be split into 2 separte UndoRedo classes. + * + * @return + */ + public boolean isHuman(){ + return true; + } + + public long recordTime() + { + return recordTime; + } + + public void setRecordTime(long recordTime) { + this.recordTime = recordTime; + } + + /** Free resources associated with this. */ + @Override + public void recycle(boolean invert){} + + public String action() + { + return action; + } + +} diff --git a/simplCore/src/ecologylab/oodss/logging/NIOLoggingServer.java b/simplCore/src/ecologylab/oodss/logging/NIOLoggingServer.java index 8139c35f..ed4358a0 100644 --- a/simplCore/src/ecologylab/oodss/logging/NIOLoggingServer.java +++ b/simplCore/src/ecologylab/oodss/logging/NIOLoggingServer.java @@ -1,201 +1,201 @@ -package ecologylab.oodss.logging; - -import java.io.IOException; -import java.net.BindException; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.nio.channels.SelectionKey; - -import ecologylab.collections.Scope; -import ecologylab.generic.Debug; -import ecologylab.net.NetTools; -import ecologylab.oodss.distributed.common.ServicesHostsAndPorts; -import ecologylab.oodss.distributed.server.DoubleThreadedNIOServer; -import ecologylab.oodss.messages.DefaultServicesTranslations; -import ecologylab.serialization.SimplTypesScope; - -/** - * A server that automatically records any incoming log data to a local file. The file is specified - * by the Prologue provided by the Logging client. - * - * @see ecologylab.oodss.logging.Logging - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class NIOLoggingServer extends DoubleThreadedNIOServer implements ServicesHostsAndPorts -{ - String logFilesPath = ""; - - public static final String LOG_FILES_PATH = "LOG_FILES_PATH"; - - public static final Class LOGGING_CLASSES[] = - { LogOps.class, LogEvent.class, - LogueMessage.class, Prologue.class, SendEpilogue.class, SendPrologue.class, - MixedInitiativeOp.class, Epilogue.class }; - - public static final int MAX_MESSAGE_SIZE_CHARS_LOGGING = 1024 * 1024; // 1MB - - /** - * This is the actual way to create an instance of this. - * - * @param portNumber - * @param translationScope - * @param objectRegistry - * @param authListFilename - * - a file name indicating the location of the authentication list; this should be an - * XML file of an AuthenticationList object. - * @return A server instance, or null if it was not possible to open a ServerSocket on the port on - * this machine. - */ - public static NIOLoggingServer getInstance(InetAddress inetAddress, Scope objectRegistry, - int idleConnectionTimeout, int maxPacketSize) - { - InetAddress[] addr = - { inetAddress }; - - return getInstance(addr, objectRegistry, idleConnectionTimeout, maxPacketSize); - } - - /** - * This is the actual way to create an instance of this. - * - * @param portNumber - * @param translationScope - * @param objectRegistry - * @param authListFilename - * - a file name indicating the location of the authentication list; this should be an - * XML file of an AuthenticationList object. - * @return A server instance, or null if it was not possible to open a ServerSocket on the port on - * this machine. - */ - public static NIOLoggingServer getInstance(InetAddress[] inetAddress, Scope objectRegistry, - int idleConnectionTimeout, int maxPacketSize) - { - NIOLoggingServer newServer = null; - - try - { - newServer = new NIOLoggingServer(LOGGING_PORT, inetAddress, null, objectRegistry, - idleConnectionTimeout, maxPacketSize); - } - catch (IOException e) - { - println("ServicesServer ERROR: can't open ServerSocket on port " + LOGGING_PORT); - e.printStackTrace(); - } - - return newServer; - } - - /** - * Launches an instance of the logging server. - * - * @param args - * the parameters for the server instance: first argument is the local directory to which - * to write files; second argument is the maximum packet size to accept from the client. - * @throws UnknownHostException - */ - public static void main(String args[]) throws UnknownHostException - { - int mPL = MAX_MESSAGE_SIZE_CHARS_LOGGING; - - if (args.length > 1) - { - try - { - int newMPL = Integer.parseInt(args[1]); - mPL = newMPL; - } - catch (NumberFormatException e) - { - Debug.println("second argument was not an integer, using MAX_MESSAGE_SIZE_CHARS_LOGGING: " - + MAX_MESSAGE_SIZE_CHARS_LOGGING); - e.printStackTrace(); - } - } - else - { - Debug.println("No max packet length specified, using " + mPL); - } - - NIOLoggingServer loggingServer = getInstance(NetTools.getAllInetAddressesForLocalhost(), - new Scope(), -1, mPL); - - if (loggingServer != null) - { - if (args.length > 0) - { - loggingServer.setLogFilesPath(args[0]); - } - - if (args.length > 2) - Debug.setLoggingFile(args[2]); - - loggingServer.start(); - } - } - - protected NIOLoggingServer(int portNumber, InetAddress[] inetAddresses, - SimplTypesScope requestTranslationSpace, Scope applicationObjectScope, - int idleConnectionTimeout, int maxPacketSize) throws IOException, BindException - { - super(portNumber, inetAddresses, SimplTypesScope.get(connectionTscopeName(inetAddresses, - portNumber), DefaultServicesTranslations.get(), requestTranslationSpace, LOGGING_CLASSES), - applicationObjectScope, idleConnectionTimeout, maxPacketSize); - - // add the necessary scope object mappings for logging - // note this is probably null right now... - this.applicationObjectScope.put(LOG_FILES_PATH, this.logFilesPath); - } - - /** - * Sets the directory to which to write log files. - * - * @param path - */ - public void setLogFilesPath(String path) - { - logFilesPath = path; - - this.applicationObjectScope.put(LOG_FILES_PATH, this.logFilesPath); - } - - /** - * @return the log file path. - */ - public String getLogFilesPath() - { - return logFilesPath; - } - - @Override - protected LoggingClientSessionManager generateContextManager(String sessionId, SelectionKey sk, - SimplTypesScope translationScopeIn, Scope registryIn) - { - return new LoggingClientSessionManager(sessionId, maxMessageSize, this, this.getBackend(), sk, - translationScopeIn, registryIn); - } - - /** - * Displays some information about the logging server, then calls super.start() - * - * @see ecologylab.oodss.distributed.server.DoubleThreadedNIOServer#start() - */ - @Override - public void start() - { - this.debug("------------------------ Logging Server starting ------------------------"); - this.debug(" max packet length: " + this.maxMessageSize); - this.debug(" saving logs to: " + this.logFilesPath); - this.debug(" operating on port: " + this.getBackend().getPortNumber()); - this.debug("using the following interfaces: "); - - for (InetAddress i : this.getBackend().getBoundAddresses()) - { - this.debug(" " + i.toString()); - } - - super.start(); - } -} +package ecologylab.oodss.logging; + +import java.io.IOException; +import java.net.BindException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.channels.SelectionKey; + +import ecologylab.collections.Scope; +import ecologylab.generic.Debug; +import ecologylab.net.NetTools; +import ecologylab.oodss.distributed.common.ServicesHostsAndPorts; +import ecologylab.oodss.distributed.server.DoubleThreadedNIOServer; +import ecologylab.oodss.messages.DefaultServicesTranslations; +import ecologylab.serialization.SimplTypesScope; + +/** + * A server that automatically records any incoming log data to a local file. The file is specified + * by the Prologue provided by the Logging client. + * + * @see ecologylab.oodss.logging.Logging + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class NIOLoggingServer extends DoubleThreadedNIOServer implements ServicesHostsAndPorts +{ + String logFilesPath = ""; + + public static final String LOG_FILES_PATH = "LOG_FILES_PATH"; + + public static final Class LOGGING_CLASSES[] = + { LogOps.class, LogEvent.class, + LogueMessage.class, Prologue.class, SendEpilogue.class, SendPrologue.class, + MixedInitiativeOp.class, Epilogue.class }; + + public static final int MAX_MESSAGE_SIZE_CHARS_LOGGING = 1024 * 1024; // 1MB + + /** + * This is the actual way to create an instance of this. + * + * @param portNumber + * @param translationScope + * @param objectRegistry + * @param authListFilename + * - a file name indicating the location of the authentication list; this should be an + * XML file of an AuthenticationList object. + * @return A server instance, or null if it was not possible to open a ServerSocket on the port on + * this machine. + */ + public static NIOLoggingServer getInstance(InetAddress inetAddress, Scope objectRegistry, + int idleConnectionTimeout, int maxPacketSize) + { + InetAddress[] addr = + { inetAddress }; + + return getInstance(addr, objectRegistry, idleConnectionTimeout, maxPacketSize); + } + + /** + * This is the actual way to create an instance of this. + * + * @param portNumber + * @param translationScope + * @param objectRegistry + * @param authListFilename + * - a file name indicating the location of the authentication list; this should be an + * XML file of an AuthenticationList object. + * @return A server instance, or null if it was not possible to open a ServerSocket on the port on + * this machine. + */ + public static NIOLoggingServer getInstance(InetAddress[] inetAddress, Scope objectRegistry, + int idleConnectionTimeout, int maxPacketSize) + { + NIOLoggingServer newServer = null; + + try + { + newServer = new NIOLoggingServer(LOGGING_PORT, inetAddress, null, objectRegistry, + idleConnectionTimeout, maxPacketSize); + } + catch (IOException e) + { + println("ServicesServer ERROR: can't open ServerSocket on port " + LOGGING_PORT); + e.printStackTrace(); + } + + return newServer; + } + + /** + * Launches an instance of the logging server. + * + * @param args + * the parameters for the server instance: first argument is the local directory to which + * to write files; second argument is the maximum packet size to accept from the client. + * @throws UnknownHostException + */ + public static void main(String args[]) throws UnknownHostException + { + int mPL = MAX_MESSAGE_SIZE_CHARS_LOGGING; + + if (args.length > 1) + { + try + { + int newMPL = Integer.parseInt(args[1]); + mPL = newMPL; + } + catch (NumberFormatException e) + { + Debug.println("second argument was not an integer, using MAX_MESSAGE_SIZE_CHARS_LOGGING: " + + MAX_MESSAGE_SIZE_CHARS_LOGGING); + e.printStackTrace(); + } + } + else + { + Debug.println("No max packet length specified, using " + mPL); + } + + NIOLoggingServer loggingServer = getInstance(NetTools.getAllInetAddressesForLocalhost(), + new Scope(), -1, mPL); + + if (loggingServer != null) + { + if (args.length > 0) + { + loggingServer.setLogFilesPath(args[0]); + } + + if (args.length > 2) + Debug.setLoggingFile(args[2]); + + loggingServer.start(); + } + } + + protected NIOLoggingServer(int portNumber, InetAddress[] inetAddresses, + SimplTypesScope requestTranslationSpace, Scope applicationObjectScope, + int idleConnectionTimeout, int maxPacketSize) throws IOException, BindException + { + super(portNumber, inetAddresses, SimplTypesScope.get(connectionTscopeName(inetAddresses, + portNumber), DefaultServicesTranslations.get(), requestTranslationSpace, LOGGING_CLASSES), + applicationObjectScope, idleConnectionTimeout, maxPacketSize); + + // add the necessary scope object mappings for logging + // note this is probably null right now... + this.applicationObjectScope.put(LOG_FILES_PATH, this.logFilesPath); + } + + /** + * Sets the directory to which to write log files. + * + * @param path + */ + public void setLogFilesPath(String path) + { + logFilesPath = path; + + this.applicationObjectScope.put(LOG_FILES_PATH, this.logFilesPath); + } + + /** + * @return the log file path. + */ + public String getLogFilesPath() + { + return logFilesPath; + } + + @Override + protected LoggingClientSessionManager generateContextManager(String sessionId, SelectionKey sk, + SimplTypesScope translationScopeIn, Scope registryIn) + { + return new LoggingClientSessionManager(sessionId, maxMessageSize, this, this.getBackend(), sk, + translationScopeIn, registryIn); + } + + /** + * Displays some information about the logging server, then calls super.start() + * + * @see ecologylab.oodss.distributed.server.DoubleThreadedNIOServer#start() + */ + @Override + public void start() + { + this.debug("------------------------ Logging Server starting ------------------------"); + this.debug(" max packet length: " + this.maxMessageSize); + this.debug(" saving logs to: " + this.logFilesPath); + this.debug(" operating on port: " + this.getBackend().getPortNumber()); + this.debug("using the following interfaces: "); + + for (InetAddress i : this.getBackend().getBoundAddresses()) + { + this.debug(" " + i.toString()); + } + + super.start(); + } +} diff --git a/simplCore/src/ecologylab/oodss/logging/Prologue.java b/simplCore/src/ecologylab/oodss/logging/Prologue.java index 9c151a1b..a3ae4bb4 100644 --- a/simplCore/src/ecologylab/oodss/logging/Prologue.java +++ b/simplCore/src/ecologylab/oodss/logging/Prologue.java @@ -1,89 +1,89 @@ -package ecologylab.oodss.logging; - -import java.util.Date; - -import ecologylab.appframework.types.prefs.Pref; -import ecologylab.net.NetTools; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * request message for the Logging server to open new log file and write the header. - * - * @author eunyee - */ -public class Prologue extends ElementState -{ - public static final String STUDY_NAME = "study_name"; - - @simpl_scalar - protected String date = new Date(System.currentTimeMillis()).toString(); - - @simpl_scalar - protected String ip = NetTools.localHost(); - - @simpl_scalar - protected String userID = "0"; - - @simpl_scalar - protected String questionId; - - @simpl_scalar - protected String studyName; - - @simpl_scalar - protected String questionPath; - - public Prologue() - { - super(); - this.userID = Pref.lookupString("uid", "0"); - this.questionId = Pref.lookupString("questionId"); - this.studyName = Pref.lookupString(STUDY_NAME); - } - - public void setUserID(String id) - { - this.userID = id; - } - - public String getUserID() - { - return this.userID; - } - - public void setStudyName(String studyName) - { - this.studyName = studyName; - } - - public String getStudyName() - { - return studyName; - } - - public void setQuestionId(String questionId) - { - this.questionId = questionId; - } - - public String getQuestionId() - { - return questionId; - } - - public String getIp() - { - return ip; - } - - public String getDate() - { - return date; - } - - public String getQuestionPath() - { - return questionPath; - } +package ecologylab.oodss.logging; + +import java.util.Date; + +import ecologylab.appframework.types.prefs.Pref; +import ecologylab.net.NetTools; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * request message for the Logging server to open new log file and write the header. + * + * @author eunyee + */ +public class Prologue extends ElementState +{ + public static final String STUDY_NAME = "study_name"; + + @simpl_scalar + protected String date = new Date(System.currentTimeMillis()).toString(); + + @simpl_scalar + protected String ip = NetTools.localHost(); + + @simpl_scalar + protected String userID = "0"; + + @simpl_scalar + protected String questionId; + + @simpl_scalar + protected String studyName; + + @simpl_scalar + protected String questionPath; + + public Prologue() + { + super(); + this.userID = Pref.lookupString("uid", "0"); + this.questionId = Pref.lookupString("questionId"); + this.studyName = Pref.lookupString(STUDY_NAME); + } + + public void setUserID(String id) + { + this.userID = id; + } + + public String getUserID() + { + return this.userID; + } + + public void setStudyName(String studyName) + { + this.studyName = studyName; + } + + public String getStudyName() + { + return studyName; + } + + public void setQuestionId(String questionId) + { + this.questionId = questionId; + } + + public String getQuestionId() + { + return questionId; + } + + public String getIp() + { + return ip; + } + + public String getDate() + { + return date; + } + + public String getQuestionPath() + { + return questionPath; + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/oodss/logging/SendEpilogue.java b/simplCore/src/ecologylab/oodss/logging/SendEpilogue.java index bb424158..b822d496 100644 --- a/simplCore/src/ecologylab/oodss/logging/SendEpilogue.java +++ b/simplCore/src/ecologylab/oodss/logging/SendEpilogue.java @@ -1,97 +1,97 @@ -package ecologylab.oodss.logging; - -import java.io.IOException; -import java.io.Writer; - -import ecologylab.oodss.messages.ErrorResponse; -import ecologylab.oodss.messages.OkResponse; -import ecologylab.oodss.messages.ResponseMessage; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * Allows the application to send application-specific content to the log, at - * the end of a session.

NB: this class should *never* be extended in an - * application specific way, because the LoggingServer should never need to know - * the TranslationSpace for such a super class. What you do extend is the - * {@link Epilogue Epilogue} object. - * - * @author andruid - * @author eunyee - */ -@simpl_inherit public final class SendEpilogue extends LogueMessage -{ - public SendEpilogue(Logging logging, Epilogue epilogue) - { - super(logging); - try - { - bufferToLog = SimplTypesScope.serialize(epilogue, StringFormat.XML);//epilogue.serialize((StringBuilder) null); - bufferToLog.insert(0, Logging.OP_SEQUENCE_END); - bufferToLog.append(endLog()); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - } - - public SendEpilogue() - { - super(); - } - - public String endLog() - { - return ""; - } - - @Override public ResponseMessage performService(LoggingContextScope contextScope) - { - debug("received epiliogue"); - - // let the superclass handle writing any epilogue data - ResponseMessage msg = super.performService(contextScope); - - // get the stream to shut it down - if (msg.isOK()) - { - Writer outputStreamWriter = contextScope.getOutputStreamWriter(); - - if (outputStreamWriter != null) - { - try - { - outputStreamWriter.flush(); - outputStreamWriter.close(); - - return OkResponse.get(); - } - catch (IOException e) - { - e.printStackTrace(); - - return new ErrorResponse(e.getMessage()); - } - finally - { - // remove the output stream from the scope - contextScope.shutdown(); - } - } - else - { - error("can't log because there is no outputStreamWriter; was there a prologue?"); - - return new ErrorResponse( - "can't log because there is no outputStreamWriter; was there a prologue?"); - } - } - else - { - return msg; - } - } -} +package ecologylab.oodss.logging; + +import java.io.IOException; +import java.io.Writer; + +import ecologylab.oodss.messages.ErrorResponse; +import ecologylab.oodss.messages.OkResponse; +import ecologylab.oodss.messages.ResponseMessage; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * Allows the application to send application-specific content to the log, at + * the end of a session.

NB: this class should *never* be extended in an + * application specific way, because the LoggingServer should never need to know + * the TranslationSpace for such a super class. What you do extend is the + * {@link Epilogue Epilogue} object. + * + * @author andruid + * @author eunyee + */ +@simpl_inherit public final class SendEpilogue extends LogueMessage +{ + public SendEpilogue(Logging logging, Epilogue epilogue) + { + super(logging); + try + { + bufferToLog = SimplTypesScope.serialize(epilogue, StringFormat.XML);//epilogue.serialize((StringBuilder) null); + bufferToLog.insert(0, Logging.OP_SEQUENCE_END); + bufferToLog.append(endLog()); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + } + + public SendEpilogue() + { + super(); + } + + public String endLog() + { + return ""; + } + + @Override public ResponseMessage performService(LoggingContextScope contextScope) + { + debug("received epiliogue"); + + // let the superclass handle writing any epilogue data + ResponseMessage msg = super.performService(contextScope); + + // get the stream to shut it down + if (msg.isOK()) + { + Writer outputStreamWriter = contextScope.getOutputStreamWriter(); + + if (outputStreamWriter != null) + { + try + { + outputStreamWriter.flush(); + outputStreamWriter.close(); + + return OkResponse.get(); + } + catch (IOException e) + { + e.printStackTrace(); + + return new ErrorResponse(e.getMessage()); + } + finally + { + // remove the output stream from the scope + contextScope.shutdown(); + } + } + else + { + error("can't log because there is no outputStreamWriter; was there a prologue?"); + + return new ErrorResponse( + "can't log because there is no outputStreamWriter; was there a prologue?"); + } + } + else + { + return msg; + } + } +} diff --git a/simplCore/src/ecologylab/oodss/logging/SendPrologue.java b/simplCore/src/ecologylab/oodss/logging/SendPrologue.java index cda6ffa4..ac343e08 100644 --- a/simplCore/src/ecologylab/oodss/logging/SendPrologue.java +++ b/simplCore/src/ecologylab/oodss/logging/SendPrologue.java @@ -1,155 +1,155 @@ -package ecologylab.oodss.logging; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Date; - -import ecologylab.appframework.types.prefs.Pref; -import ecologylab.io.Files; -import ecologylab.net.NetTools; -import ecologylab.oodss.messages.ErrorResponse; -import ecologylab.oodss.messages.ResponseMessage; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * Allows the application to send application-specific content to the log, at the beginning of a - * session. - *

- * NB: this class should *never* be extended in an application specific way, because the - * LoggingServer should never need to know the TranslationSpace for such a super class. What you do - * extend is the {@link Prologue Prologue} object. - * - * @author andruid - * @author eunyee - */ -@simpl_inherit -public final class SendPrologue extends LogueMessage -{ - @simpl_scalar - protected String date = new Date(System.currentTimeMillis()).toString(); - - @simpl_scalar - protected String ip = NetTools.localHost(); - - @simpl_scalar - protected String userID = "0"; - - @simpl_scalar - protected String studyName; - - @simpl_scalar - protected boolean performEpilogueNow; - - public SendPrologue(Logging logging, Prologue prologue) - { - super(logging); - this.date = prologue.date; - this.ip = prologue.ip; - this.userID = prologue.userID; - this.studyName = prologue.getStudyName(); - try - { - bufferToLog = SimplTypesScope.serialize(prologue, StringFormat.XML);//prologue.serialize((StringBuilder) null); - bufferToLog.insert(0, beginLog()); - bufferToLog.append(Logging.OP_SEQUENCE_START); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - } - - public SendPrologue() - { - super(); - } - - public String getFileName() - { - String tempDate = date.replace(' ', '_'); - tempDate = tempDate.replace(':', '_'); - /** - * A session log file name of a user - */ - String sessionLogFile = // "/project/ecologylab/studyResults/CF_LOG/" + - // "LogFiles/" + - ip + "__" + tempDate + "_" + userID + ".xml"; - String studyName = getStudyName(); - if (studyName != null) - sessionLogFile = studyName + Files.sep + sessionLogFile; - return sessionLogFile; - } - - public static String constructFileName() - { - return getFileName(new Date(), Pref.lookupString(Prologue.STUDY_NAME)); - } - - public static String getFileName(Date date, String studyName) - { - String tempDate = date.toString().replace(' ', '_'); - tempDate = tempDate.replace(':', '_'); - - String ip = NetTools.localHost(); - /** - * A session log file name of a user - */ - String sessionLogFile = // "/project/ecologylab/studyResults/CF_LOG/" + - // "LogFiles/" + - ip + "__" + tempDate + "_" + Pref.lookupString("uid", "No UID") + ".xml"; - - if (studyName != null) - sessionLogFile = studyName + Files.sep + sessionLogFile; - return sessionLogFile; - } - - public String beginLog() - { - return XMLTools.xmlHeader() + "\n<" + logName() + ">\n\n"; - } - - public String getStudyName() - { - return studyName; - } - - /** - * First, configure OUTPUT_WRITER, then, in case we have some data, do super.performService(...) - * to write it out to the file. - */ - @Override - public ResponseMessage performService(LoggingContextScope contextScope) - { - try - { - contextScope.setUpOutputStreamWriter(this.getFileName()); - - if (this.performEpilogueNow) - { - SendEpilogue se = new SendEpilogue(); - se.bufferToLog = this.bufferToLog; - // this will write the buffer and then close the file - return se.performService(contextScope); - } - else - return super.performService(contextScope); - } - catch (FileNotFoundException e) - { - e.printStackTrace(); - - return new ErrorResponse(e.getMessage()); - } - catch (IOException e) - { - e.printStackTrace(); - - return new ErrorResponse(e.getMessage()); - } - } -} +package ecologylab.oodss.logging; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Date; + +import ecologylab.appframework.types.prefs.Pref; +import ecologylab.io.Files; +import ecologylab.net.NetTools; +import ecologylab.oodss.messages.ErrorResponse; +import ecologylab.oodss.messages.ResponseMessage; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * Allows the application to send application-specific content to the log, at the beginning of a + * session. + *

+ * NB: this class should *never* be extended in an application specific way, because the + * LoggingServer should never need to know the TranslationSpace for such a super class. What you do + * extend is the {@link Prologue Prologue} object. + * + * @author andruid + * @author eunyee + */ +@simpl_inherit +public final class SendPrologue extends LogueMessage +{ + @simpl_scalar + protected String date = new Date(System.currentTimeMillis()).toString(); + + @simpl_scalar + protected String ip = NetTools.localHost(); + + @simpl_scalar + protected String userID = "0"; + + @simpl_scalar + protected String studyName; + + @simpl_scalar + protected boolean performEpilogueNow; + + public SendPrologue(Logging logging, Prologue prologue) + { + super(logging); + this.date = prologue.date; + this.ip = prologue.ip; + this.userID = prologue.userID; + this.studyName = prologue.getStudyName(); + try + { + bufferToLog = SimplTypesScope.serialize(prologue, StringFormat.XML);//prologue.serialize((StringBuilder) null); + bufferToLog.insert(0, beginLog()); + bufferToLog.append(Logging.OP_SEQUENCE_START); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + } + + public SendPrologue() + { + super(); + } + + public String getFileName() + { + String tempDate = date.replace(' ', '_'); + tempDate = tempDate.replace(':', '_'); + /** + * A session log file name of a user + */ + String sessionLogFile = // "/project/ecologylab/studyResults/CF_LOG/" + + // "LogFiles/" + + ip + "__" + tempDate + "_" + userID + ".xml"; + String studyName = getStudyName(); + if (studyName != null) + sessionLogFile = studyName + Files.sep + sessionLogFile; + return sessionLogFile; + } + + public static String constructFileName() + { + return getFileName(new Date(), Pref.lookupString(Prologue.STUDY_NAME)); + } + + public static String getFileName(Date date, String studyName) + { + String tempDate = date.toString().replace(' ', '_'); + tempDate = tempDate.replace(':', '_'); + + String ip = NetTools.localHost(); + /** + * A session log file name of a user + */ + String sessionLogFile = // "/project/ecologylab/studyResults/CF_LOG/" + + // "LogFiles/" + + ip + "__" + tempDate + "_" + Pref.lookupString("uid", "No UID") + ".xml"; + + if (studyName != null) + sessionLogFile = studyName + Files.sep + sessionLogFile; + return sessionLogFile; + } + + public String beginLog() + { + return XMLTools.xmlHeader() + "\n<" + logName() + ">\n\n"; + } + + public String getStudyName() + { + return studyName; + } + + /** + * First, configure OUTPUT_WRITER, then, in case we have some data, do super.performService(...) + * to write it out to the file. + */ + @Override + public ResponseMessage performService(LoggingContextScope contextScope) + { + try + { + contextScope.setUpOutputStreamWriter(this.getFileName()); + + if (this.performEpilogueNow) + { + SendEpilogue se = new SendEpilogue(); + se.bufferToLog = this.bufferToLog; + // this will write the buffer and then close the file + return se.performService(contextScope); + } + else + return super.performService(contextScope); + } + catch (FileNotFoundException e) + { + e.printStackTrace(); + + return new ErrorResponse(e.getMessage()); + } + catch (IOException e) + { + e.printStackTrace(); + + return new ErrorResponse(e.getMessage()); + } + } +} diff --git a/simplCore/src/ecologylab/oodss/logging/package.html b/simplCore/src/ecologylab/oodss/logging/package.html index 33923128..27d04d39 100644 --- a/simplCore/src/ecologylab/oodss/logging/package.html +++ b/simplCore/src/ecologylab/oodss/logging/package.html @@ -1,3 +1,3 @@ - -Interface Ecology Lab Logging. - + +Interface Ecology Lab Logging. + diff --git a/simplCore/src/ecologylab/oodss/logging/playback/ExtensionFilter.java b/simplCore/src/ecologylab/oodss/logging/playback/ExtensionFilter.java index 6bc7eab3..6ad94b4e 100644 --- a/simplCore/src/ecologylab/oodss/logging/playback/ExtensionFilter.java +++ b/simplCore/src/ecologylab/oodss/logging/playback/ExtensionFilter.java @@ -1,41 +1,41 @@ -/** - * - */ -package ecologylab.oodss.logging.playback; - -import java.io.File; - -/** - * Log files should be XML files; this file filter only displays files whose filetype is XML. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public class ExtensionFilter extends javax.swing.filechooser.FileFilter implements java.io.FileFilter -{ - private String extension; - - public ExtensionFilter(String extension) - { - this.extension = extension; - } - - /** - * @see javax.swing.filechooser.FileFilter#accept(java.io.File) - */ - @Override public boolean accept(File arg0) - { - if (arg0.isDirectory()) - return true; - - String fileName = arg0.toString(); - return (extension.equalsIgnoreCase(fileName.substring(fileName.lastIndexOf('.') + 1))); - } - - /** - * @see javax.swing.filechooser.FileFilter#getDescription() - */ - @Override public String getDescription() - { - return extension; - } -} +/** + * + */ +package ecologylab.oodss.logging.playback; + +import java.io.File; + +/** + * Log files should be XML files; this file filter only displays files whose filetype is XML. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public class ExtensionFilter extends javax.swing.filechooser.FileFilter implements java.io.FileFilter +{ + private String extension; + + public ExtensionFilter(String extension) + { + this.extension = extension; + } + + /** + * @see javax.swing.filechooser.FileFilter#accept(java.io.File) + */ + @Override public boolean accept(File arg0) + { + if (arg0.isDirectory()) + return true; + + String fileName = arg0.toString(); + return (extension.equalsIgnoreCase(fileName.substring(fileName.lastIndexOf('.') + 1))); + } + + /** + * @see javax.swing.filechooser.FileFilter#getDescription() + */ + @Override public String getDescription() + { + return extension; + } +} diff --git a/simplCore/src/ecologylab/oodss/logging/playback/LogPlaybackControlModel.java b/simplCore/src/ecologylab/oodss/logging/playback/LogPlaybackControlModel.java index c9c11fbf..c284b519 100644 --- a/simplCore/src/ecologylab/oodss/logging/playback/LogPlaybackControlModel.java +++ b/simplCore/src/ecologylab/oodss/logging/playback/LogPlaybackControlModel.java @@ -1,263 +1,263 @@ -/* - * Created on Apr 12, 2007 - */ -package ecologylab.oodss.logging.playback; - -import java.util.LinkedList; -import java.util.List; - -import javax.swing.BoundedRangeModel; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import ecologylab.generic.Debug; -import ecologylab.oodss.logging.Logging; -import ecologylab.oodss.logging.MixedInitiativeOp; -import ecologylab.oodss.logging.Prologue; - -/** - * Model of playback for logged operations. Controls advancement through a log during playback, as well as rewind, etc. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public class LogPlaybackControlModel> implements BoundedRangeModel -{ - protected T log; - - private int currentPlaybackOp = 0; - - private boolean singleEventMode = false; - - private List changeListeners = new LinkedList(); - - protected long startTime = 0; - - /** - * - */ - public LogPlaybackControlModel(T log) - { - this.log = log; - } - - public T getLog() - { - return log; - } - - /** - * Returns the control to the first op. - * - */ - public void reset() - { - this.setPlaybackOpTo(0); - } - - /** - * Advances the current op by one. - * - */ - public void forward() - { - this.setPlaybackOpTo(currentPlaybackOp + 1); - } - - /** - * Moves back one op. - * - */ - public void back() - { - this.setPlaybackOpTo(currentPlaybackOp - 1); - } - - public E getCurrentOp() - { - return log.getOpSequence().get(currentPlaybackOp); - } - - /** - * @see javax.swing.BoundedRangeModel#addChangeListener(javax.swing.event.ChangeListener) - */ - @Override - public void addChangeListener(ChangeListener arg0) - { - changeListeners.add(arg0); - } - - /** - * @see javax.swing.BoundedRangeModel#getExtent() - */ - @Override - public int getExtent() - { - return log.size(); - } - - /** - * @see javax.swing.BoundedRangeModel#getMaximum() - */ - @Override - public int getMaximum() - { - return log.size() - 1; - } - - /** - * @see javax.swing.BoundedRangeModel#getMinimum() - */ - @Override - public int getMinimum() - { - return 0; - } - - /** - * @see javax.swing.BoundedRangeModel#getValue() - */ - @Override - public int getValue() - { - return currentPlaybackOp; - } - - /** - * @see javax.swing.BoundedRangeModel#getValueIsAdjusting() - */ - @Override - public boolean getValueIsAdjusting() - { - return singleEventMode; - } - - /** - * @see javax.swing.BoundedRangeModel#removeChangeListener(javax.swing.event.ChangeListener) - */ - @Override - public void removeChangeListener(ChangeListener arg0) - { - changeListeners.remove(arg0); - } - - /** - * Throws an UnsupportedOperationException; minimum is set by the underlying log data. - * - * @see javax.swing.BoundedRangeModel#setMinimum(int) - */ - @Override - public void setMinimum(int arg0) throws UnsupportedOperationException - { - throw new UnsupportedOperationException("Cannot set minimum."); - } - - /** - * Throws an UnsupportedOperationException; maximum is set by the underlying log data. - * - * @see javax.swing.BoundedRangeModel#setMaximum(int) - */ - @Override - public void setMaximum(int arg0) throws UnsupportedOperationException - { - throw new UnsupportedOperationException("Cannot set maximum."); - } - - @Override - public void setExtent(int arg0) throws UnsupportedOperationException - { - throw new UnsupportedOperationException("Extent set by underlying data; cannot set extent manually."); - } - - @Override - public void setRangeProperties(int arg0, int arg1, int arg2, int arg3, boolean arg4) - { - throw new UnsupportedOperationException( - "Range properties set by underlying data; cannot set properties manually."); - } - - /** - * @see javax.swing.BoundedRangeModel#setValue(int) - */ - @Override - public void setValue(int arg0) - { - this.setPlaybackOpTo(arg0); - } - - protected void setPlaybackOpTo(int index) - { - if (index > (this.getMaximum())) - { - setPlaybackOpTo(this.getMaximum()); - } - else if (index < 0) - { - setPlaybackOpTo(0); - } - else - { - currentPlaybackOp = index; - } - - if (!singleEventMode) - { - this.fireChangeEvent(); - } - } - - /** - * @see javax.swing.BoundedRangeModel#setValueIsAdjusting(boolean) - */ - @Override - public void setValueIsAdjusting(boolean arg0) - { - // if (singleEventMode && !arg0) - // { // transition from true to false fires events - // this.fireChangeEvent(); - // } - - // this.singleEventMode = arg0; - } - - private void fireChangeEvent() - { - for (ChangeListener l : changeListeners) - { - l.stateChanged(new ChangeEvent(this)); - } - } - - /** - * Returns the next operation after the current one if one exists, otherwise returns the current operation. - * - * @return - */ - public E getNext() - { - if (this.currentPlaybackOp != (this.getMaximum())) - { - return log.getOpSequence().get(currentPlaybackOp + 1); - } - else - { - Debug.println("last op"); - return this.getCurrentOp(); - } - } - - public Prologue getLogPrologue() - { - return this.log.getPrologue(); - } - - public void setStartPoint() - { - startTime = this.getCurrentOp().getSessionTime(); - } - - public long getTimeOffset() - { - return this.getCurrentOp().getSessionTime() - startTime; - } - -} +/* + * Created on Apr 12, 2007 + */ +package ecologylab.oodss.logging.playback; + +import java.util.LinkedList; +import java.util.List; + +import javax.swing.BoundedRangeModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import ecologylab.generic.Debug; +import ecologylab.oodss.logging.Logging; +import ecologylab.oodss.logging.MixedInitiativeOp; +import ecologylab.oodss.logging.Prologue; + +/** + * Model of playback for logged operations. Controls advancement through a log during playback, as well as rewind, etc. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public class LogPlaybackControlModel> implements BoundedRangeModel +{ + protected T log; + + private int currentPlaybackOp = 0; + + private boolean singleEventMode = false; + + private List changeListeners = new LinkedList(); + + protected long startTime = 0; + + /** + * + */ + public LogPlaybackControlModel(T log) + { + this.log = log; + } + + public T getLog() + { + return log; + } + + /** + * Returns the control to the first op. + * + */ + public void reset() + { + this.setPlaybackOpTo(0); + } + + /** + * Advances the current op by one. + * + */ + public void forward() + { + this.setPlaybackOpTo(currentPlaybackOp + 1); + } + + /** + * Moves back one op. + * + */ + public void back() + { + this.setPlaybackOpTo(currentPlaybackOp - 1); + } + + public E getCurrentOp() + { + return log.getOpSequence().get(currentPlaybackOp); + } + + /** + * @see javax.swing.BoundedRangeModel#addChangeListener(javax.swing.event.ChangeListener) + */ + @Override + public void addChangeListener(ChangeListener arg0) + { + changeListeners.add(arg0); + } + + /** + * @see javax.swing.BoundedRangeModel#getExtent() + */ + @Override + public int getExtent() + { + return log.size(); + } + + /** + * @see javax.swing.BoundedRangeModel#getMaximum() + */ + @Override + public int getMaximum() + { + return log.size() - 1; + } + + /** + * @see javax.swing.BoundedRangeModel#getMinimum() + */ + @Override + public int getMinimum() + { + return 0; + } + + /** + * @see javax.swing.BoundedRangeModel#getValue() + */ + @Override + public int getValue() + { + return currentPlaybackOp; + } + + /** + * @see javax.swing.BoundedRangeModel#getValueIsAdjusting() + */ + @Override + public boolean getValueIsAdjusting() + { + return singleEventMode; + } + + /** + * @see javax.swing.BoundedRangeModel#removeChangeListener(javax.swing.event.ChangeListener) + */ + @Override + public void removeChangeListener(ChangeListener arg0) + { + changeListeners.remove(arg0); + } + + /** + * Throws an UnsupportedOperationException; minimum is set by the underlying log data. + * + * @see javax.swing.BoundedRangeModel#setMinimum(int) + */ + @Override + public void setMinimum(int arg0) throws UnsupportedOperationException + { + throw new UnsupportedOperationException("Cannot set minimum."); + } + + /** + * Throws an UnsupportedOperationException; maximum is set by the underlying log data. + * + * @see javax.swing.BoundedRangeModel#setMaximum(int) + */ + @Override + public void setMaximum(int arg0) throws UnsupportedOperationException + { + throw new UnsupportedOperationException("Cannot set maximum."); + } + + @Override + public void setExtent(int arg0) throws UnsupportedOperationException + { + throw new UnsupportedOperationException("Extent set by underlying data; cannot set extent manually."); + } + + @Override + public void setRangeProperties(int arg0, int arg1, int arg2, int arg3, boolean arg4) + { + throw new UnsupportedOperationException( + "Range properties set by underlying data; cannot set properties manually."); + } + + /** + * @see javax.swing.BoundedRangeModel#setValue(int) + */ + @Override + public void setValue(int arg0) + { + this.setPlaybackOpTo(arg0); + } + + protected void setPlaybackOpTo(int index) + { + if (index > (this.getMaximum())) + { + setPlaybackOpTo(this.getMaximum()); + } + else if (index < 0) + { + setPlaybackOpTo(0); + } + else + { + currentPlaybackOp = index; + } + + if (!singleEventMode) + { + this.fireChangeEvent(); + } + } + + /** + * @see javax.swing.BoundedRangeModel#setValueIsAdjusting(boolean) + */ + @Override + public void setValueIsAdjusting(boolean arg0) + { + // if (singleEventMode && !arg0) + // { // transition from true to false fires events + // this.fireChangeEvent(); + // } + + // this.singleEventMode = arg0; + } + + private void fireChangeEvent() + { + for (ChangeListener l : changeListeners) + { + l.stateChanged(new ChangeEvent(this)); + } + } + + /** + * Returns the next operation after the current one if one exists, otherwise returns the current operation. + * + * @return + */ + public E getNext() + { + if (this.currentPlaybackOp != (this.getMaximum())) + { + return log.getOpSequence().get(currentPlaybackOp + 1); + } + else + { + Debug.println("last op"); + return this.getCurrentOp(); + } + } + + public Prologue getLogPrologue() + { + return this.log.getPrologue(); + } + + public void setStartPoint() + { + startTime = this.getCurrentOp().getSessionTime(); + } + + public long getTimeOffset() + { + return this.getCurrentOp().getSessionTime() - startTime; + } + +} diff --git a/simplCore/src/ecologylab/oodss/logging/playback/LogPlaybackControls.java b/simplCore/src/ecologylab/oodss/logging/playback/LogPlaybackControls.java index b340fafe..0167fa6d 100644 --- a/simplCore/src/ecologylab/oodss/logging/playback/LogPlaybackControls.java +++ b/simplCore/src/ecologylab/oodss/logging/playback/LogPlaybackControls.java @@ -1,280 +1,280 @@ -package ecologylab.oodss.logging.playback; - -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; - -import javax.swing.AbstractAction; -import javax.swing.BoxLayout; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JPanel; -import javax.swing.JProgressBar; -import javax.swing.JSlider; -import javax.swing.KeyStroke; -import javax.swing.SwingConstants; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import ecologylab.oodss.logging.Logging; -import ecologylab.oodss.logging.MixedInitiativeOp; - -/** - * GUI elements for the log playback application. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - * @param - * @param - */ -public class LogPlaybackControls> extends JPanel - implements ActionListener, PlaybackControlCommands, ChangeListener -{ - private static final long serialVersionUID = 1L; - - protected LogPlaybackControlModel log = null; - - private JProgressBar loadSpinner = new JProgressBar(); - - protected JSlider jogShuttle = new JSlider(); - - private ImageIcon playIcon = new ImageIcon( - "toolbarButtonGraphics/media/Play24.gif", - "Play"); - - private ImageIcon pauseIcon = new ImageIcon( - "toolbarButtonGraphics/media/Pause24.gif", - "Pause"); - - private JButton playPauseButton = new JButton(playIcon); - - private JButton stopButton = new JButton( - new ImageIcon( - "toolbarButtonGraphics/media/Stop24.gif", - "Stop")); - - private JButton stepBackButton = new JButton( - new ImageIcon( - "toolbarButtonGraphics/media/StepBack24.gif", - "Step back")); - - private JButton stepForwardButton = new JButton( - new ImageIcon( - "toolbarButtonGraphics/media/StepForward24.gif", - "Step forward")); - - protected boolean mousePressed = false; - - protected LogPlayer player; - - public LogPlaybackControls(LogPlayer p) - { - super(); - - player = p; - - this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); - - jogShuttle.setOrientation(SwingConstants.HORIZONTAL); - loadSpinner.setOrientation(SwingConstants.VERTICAL); - - playPauseButton.setActionCommand(PLAY); - stopButton.setActionCommand(STOP); - stepBackButton.setActionCommand(STEP_BACK); - stepForwardButton.setActionCommand(STEP_FORWARD); - - playPauseButton.addActionListener(player); - playPauseButton.addActionListener(this); - - playPauseButton.getInputMap(WHEN_IN_FOCUSED_WINDOW).put( - KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "UP"); - playPauseButton.getActionMap().put("UP", new ButtonAction(playPauseButton)); - - playPauseButton.getInputMap(WHEN_IN_FOCUSED_WINDOW).put( - KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "LEFT"); - playPauseButton.getActionMap().put("LEFT", new ButtonAction(stepBackButton)); - - playPauseButton.getInputMap(WHEN_IN_FOCUSED_WINDOW).put( - KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "RIGHT"); - playPauseButton.getActionMap().put("RIGHT", new ButtonAction(stepForwardButton)); - - stopButton.addActionListener(player); - stopButton.addActionListener(this); - - stepBackButton.addActionListener(player); - stepBackButton.addActionListener(this); - - stepForwardButton.addActionListener(player); - stepForwardButton.addActionListener(this); - - player.addActionListener(this); - - this.add(stepBackButton); - - JPanel playStopPanel = new JPanel(); - playStopPanel.setLayout(new BoxLayout(playStopPanel, BoxLayout.PAGE_AXIS)); - - playStopPanel.add(playPauseButton); - playStopPanel.add(stopButton); - - this.add(playStopPanel); - - this.add(stepForwardButton); - - jogShuttle.setPreferredSize(new Dimension(800, 50)); - jogShuttle.setPaintLabels(true); - - jogShuttle.addMouseListener(new MouseListener() - { - @Override - public void mousePressed(MouseEvent me) - { - jogShuttle - .setValue((int) (jogShuttle.getMinimum() + (jogShuttle.getExtent() * ((double) me - .getX() / (double) jogShuttle.getWidth())))); - player.startAdjusting(); - mousePressed = true; - } - - @Override - public void mouseClicked(MouseEvent me) - { - jogShuttle - .setValue((int) (jogShuttle.getMinimum() + (jogShuttle.getExtent() * ((double) me - .getX() / (double) jogShuttle.getWidth())))); - } - - @Override - public void mouseReleased(MouseEvent me) - { - jogShuttle - .setValue((int) (jogShuttle.getMinimum() + (jogShuttle.getExtent() * ((double) me - .getX() / (double) jogShuttle.getWidth())))); - mousePressed = false; - } - - @Override - public void mouseEntered(MouseEvent me) - { - } - - @Override - public void mouseExited(MouseEvent me) - { - } - }); - - jogShuttle.addMouseMotionListener(new MouseMotionListener() - { - - @Override - public void mouseDragged(MouseEvent me) - { - jogShuttle - .setValue((int) (jogShuttle.getMinimum() + (jogShuttle.getExtent() * ((double) me - .getX() / (double) jogShuttle.getWidth())))); - } - - @Override - public void mouseMoved(MouseEvent me) - { - } - }); - - this.add(jogShuttle); - } - - public boolean isMousePressed() - { - return mousePressed; - } - - /** - * @param loading - * The loading to set. - */ - public void setLoading(boolean loading) - { - loadSpinner.setIndeterminate(loading); - } - - /** - * @param log - * The log to set. - */ - public void setLog(LogPlaybackControlModel log) - { - this.log = log; - - jogShuttle.setModel(log); - } - - @Override - public void actionPerformed(ActionEvent arg0) - { - if (PLAY.equals(arg0.getActionCommand())) - { - play(); - } - - if (PAUSE.equals(arg0.getActionCommand()) - || STEP_BACK.equals(arg0.getActionCommand()) - || STEP_FORWARD.equals(arg0.getActionCommand()) - || STOP.equals(arg0.getActionCommand())) - { - pause(); - } - - } - - /** - * - */ - protected void pause() - { - playPauseButton.setActionCommand(PLAY); - playPauseButton.setIcon(playIcon); - } - - /** - * - */ - protected void play() - { - playPauseButton.setActionCommand(PAUSE); - playPauseButton.setIcon(pauseIcon); - } - - @Override - public void stateChanged(ChangeEvent arg0) - { - } - - /** - * Hook method for subclasses that need to set up important events on the log op timeline. - * - */ - public void setupImportantEvents() - { - } - - public class ButtonAction extends AbstractAction - { - JButton button; - - public ButtonAction(JButton button) - { - this.button = button; - } - - @Override - public void actionPerformed(ActionEvent arg0) - { - button.doClick(); - } - } -} +package ecologylab.oodss.logging.playback; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +import javax.swing.AbstractAction; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JSlider; +import javax.swing.KeyStroke; +import javax.swing.SwingConstants; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import ecologylab.oodss.logging.Logging; +import ecologylab.oodss.logging.MixedInitiativeOp; + +/** + * GUI elements for the log playback application. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + * @param + * @param + */ +public class LogPlaybackControls> extends JPanel + implements ActionListener, PlaybackControlCommands, ChangeListener +{ + private static final long serialVersionUID = 1L; + + protected LogPlaybackControlModel log = null; + + private JProgressBar loadSpinner = new JProgressBar(); + + protected JSlider jogShuttle = new JSlider(); + + private ImageIcon playIcon = new ImageIcon( + "toolbarButtonGraphics/media/Play24.gif", + "Play"); + + private ImageIcon pauseIcon = new ImageIcon( + "toolbarButtonGraphics/media/Pause24.gif", + "Pause"); + + private JButton playPauseButton = new JButton(playIcon); + + private JButton stopButton = new JButton( + new ImageIcon( + "toolbarButtonGraphics/media/Stop24.gif", + "Stop")); + + private JButton stepBackButton = new JButton( + new ImageIcon( + "toolbarButtonGraphics/media/StepBack24.gif", + "Step back")); + + private JButton stepForwardButton = new JButton( + new ImageIcon( + "toolbarButtonGraphics/media/StepForward24.gif", + "Step forward")); + + protected boolean mousePressed = false; + + protected LogPlayer player; + + public LogPlaybackControls(LogPlayer p) + { + super(); + + player = p; + + this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); + + jogShuttle.setOrientation(SwingConstants.HORIZONTAL); + loadSpinner.setOrientation(SwingConstants.VERTICAL); + + playPauseButton.setActionCommand(PLAY); + stopButton.setActionCommand(STOP); + stepBackButton.setActionCommand(STEP_BACK); + stepForwardButton.setActionCommand(STEP_FORWARD); + + playPauseButton.addActionListener(player); + playPauseButton.addActionListener(this); + + playPauseButton.getInputMap(WHEN_IN_FOCUSED_WINDOW).put( + KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "UP"); + playPauseButton.getActionMap().put("UP", new ButtonAction(playPauseButton)); + + playPauseButton.getInputMap(WHEN_IN_FOCUSED_WINDOW).put( + KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "LEFT"); + playPauseButton.getActionMap().put("LEFT", new ButtonAction(stepBackButton)); + + playPauseButton.getInputMap(WHEN_IN_FOCUSED_WINDOW).put( + KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "RIGHT"); + playPauseButton.getActionMap().put("RIGHT", new ButtonAction(stepForwardButton)); + + stopButton.addActionListener(player); + stopButton.addActionListener(this); + + stepBackButton.addActionListener(player); + stepBackButton.addActionListener(this); + + stepForwardButton.addActionListener(player); + stepForwardButton.addActionListener(this); + + player.addActionListener(this); + + this.add(stepBackButton); + + JPanel playStopPanel = new JPanel(); + playStopPanel.setLayout(new BoxLayout(playStopPanel, BoxLayout.PAGE_AXIS)); + + playStopPanel.add(playPauseButton); + playStopPanel.add(stopButton); + + this.add(playStopPanel); + + this.add(stepForwardButton); + + jogShuttle.setPreferredSize(new Dimension(800, 50)); + jogShuttle.setPaintLabels(true); + + jogShuttle.addMouseListener(new MouseListener() + { + @Override + public void mousePressed(MouseEvent me) + { + jogShuttle + .setValue((int) (jogShuttle.getMinimum() + (jogShuttle.getExtent() * ((double) me + .getX() / (double) jogShuttle.getWidth())))); + player.startAdjusting(); + mousePressed = true; + } + + @Override + public void mouseClicked(MouseEvent me) + { + jogShuttle + .setValue((int) (jogShuttle.getMinimum() + (jogShuttle.getExtent() * ((double) me + .getX() / (double) jogShuttle.getWidth())))); + } + + @Override + public void mouseReleased(MouseEvent me) + { + jogShuttle + .setValue((int) (jogShuttle.getMinimum() + (jogShuttle.getExtent() * ((double) me + .getX() / (double) jogShuttle.getWidth())))); + mousePressed = false; + } + + @Override + public void mouseEntered(MouseEvent me) + { + } + + @Override + public void mouseExited(MouseEvent me) + { + } + }); + + jogShuttle.addMouseMotionListener(new MouseMotionListener() + { + + @Override + public void mouseDragged(MouseEvent me) + { + jogShuttle + .setValue((int) (jogShuttle.getMinimum() + (jogShuttle.getExtent() * ((double) me + .getX() / (double) jogShuttle.getWidth())))); + } + + @Override + public void mouseMoved(MouseEvent me) + { + } + }); + + this.add(jogShuttle); + } + + public boolean isMousePressed() + { + return mousePressed; + } + + /** + * @param loading + * The loading to set. + */ + public void setLoading(boolean loading) + { + loadSpinner.setIndeterminate(loading); + } + + /** + * @param log + * The log to set. + */ + public void setLog(LogPlaybackControlModel log) + { + this.log = log; + + jogShuttle.setModel(log); + } + + @Override + public void actionPerformed(ActionEvent arg0) + { + if (PLAY.equals(arg0.getActionCommand())) + { + play(); + } + + if (PAUSE.equals(arg0.getActionCommand()) + || STEP_BACK.equals(arg0.getActionCommand()) + || STEP_FORWARD.equals(arg0.getActionCommand()) + || STOP.equals(arg0.getActionCommand())) + { + pause(); + } + + } + + /** + * + */ + protected void pause() + { + playPauseButton.setActionCommand(PLAY); + playPauseButton.setIcon(playIcon); + } + + /** + * + */ + protected void play() + { + playPauseButton.setActionCommand(PAUSE); + playPauseButton.setIcon(pauseIcon); + } + + @Override + public void stateChanged(ChangeEvent arg0) + { + } + + /** + * Hook method for subclasses that need to set up important events on the log op timeline. + * + */ + public void setupImportantEvents() + { + } + + public class ButtonAction extends AbstractAction + { + JButton button; + + public ButtonAction(JButton button) + { + this.button = button; + } + + @Override + public void actionPerformed(ActionEvent arg0) + { + button.doClick(); + } + } +} diff --git a/simplCore/src/ecologylab/oodss/logging/playback/LogPlayer.java b/simplCore/src/ecologylab/oodss/logging/playback/LogPlayer.java index fd5da720..0bd8cf8b 100755 --- a/simplCore/src/ecologylab/oodss/logging/playback/LogPlayer.java +++ b/simplCore/src/ecologylab/oodss/logging/playback/LogPlayer.java @@ -1,548 +1,548 @@ -package ecologylab.oodss.logging.playback; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; -import java.io.File; -import java.util.LinkedList; -import java.util.List; - -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.Timer; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; - -import ecologylab.appframework.PropertiesAndDirectories; -import ecologylab.appframework.SingletonApplicationEnvironment; -import ecologylab.oodss.logging.Logging; -import ecologylab.oodss.logging.MixedInitiativeOp; -import ecologylab.oodss.logging.translationScope.MixedInitiativeOpClassesProvider; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; - -/** - * The main application for playing back log files. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public abstract class LogPlayer> extends - SingletonApplicationEnvironment implements ActionListener, WindowListener, PlaybackControlCommands, - Runnable -{ - private static final int LOG_LOADED = 2; - - private static final int LOG_LOADING = 1; - - private static final int LOG_NOT_SELECTED = 0; - - private List actionListeners = new LinkedList(); - - protected LogPlaybackControls controlsDisplay = null; - - protected View logDisplay = null; - - protected LogPlaybackControlModel log; - - protected File logFile = null; - - protected JFrame mainFrame; - - protected boolean playing = false; - - protected Timer t; - - /** - * Modes: 0 = no file selected (need to get a file name). 1 = file selected and loading. 2 = file - * loaded, display log. - */ - - protected int mode = LOG_NOT_SELECTED; - - private boolean guiShown; - - protected SimplTypesScope translationScope; - - public final static int DEFAULT_PLAYBACK_INTERVAL = 100; - - public final static int TIMESTAMP_PLAYBACK_INTERVAL = -1; - - /** - * The number of milliseconds between ops when the log is playing. Setting to -1 will try to use - * op timestamps. - */ - protected int playbackInterval = DEFAULT_PLAYBACK_INTERVAL; - - private boolean logLoadComplete = false; - - /** - * - * @param appName - * @param args - * @param translationScope - * @param opSubclasses - * An array of subclasses of MixedInitiativeOp that will be used to translate the - * operations read in by the player. - * @throws SIMPLTranslationException - */ - public LogPlayer(String appName, String[] args, SimplTypesScope translationScope, - Class[] opSubclasses) throws SIMPLTranslationException - { - super(appName, translationScope, (SimplTypesScope) null, args, 0); - - // create a translation scope for the opSubclasses - if (opSubclasses == null) - opSubclasses = MixedInitiativeOpClassesProvider.STATIC_INSTANCE.provideClasses(); - - SimplTypesScope.get(Logging.MIXED_INITIATIVE_OP_TRANSLATION_SCOPE, opSubclasses); - - guiShown = false; - - if (translationScope != null) - this.translationScope = translationScope; - else - this.translationScope = SimplTypesScope.get(Logging.MIXED_INITIATIVE_OP_TRANSLATION_SCOPE); - - LOG incomingLog = null; - - // see if a log file has been specified - if (args.length > 1) - { // a log was specified - debug("Getting log file from args!"); - logFile = new File(args[1]); - mode = LOG_LOADING; - - logLoadComplete = false; - } - - while (incomingLog == null) - { - // Schedule a job for the event-dispatching thread: - // creating and showing this application's GUI. - javax.swing.SwingUtilities.invokeLater(this); - - while (mode != LOG_LOADING || logFile == null) - { // wait until we get a logFile or until the program quits - try - { - Thread.sleep(100); - } - catch (InterruptedException e) - { - e.printStackTrace(); - } - } - - // by now, incomingLog must have something - debug("Reading log from file: " + logFile); - - // Schedule a job for the event-dispatching thread: - // creating and showing this application's GUI. - javax.swing.SwingUtilities.invokeLater(this); - - incomingLog = this.readInXMLFile(logFile); - - if (incomingLog != null) - { - this.log = generateLogPlaybackControlModel(incomingLog); - - t = new Timer(this.playbackInterval, this); - - mode = LOG_LOADED; - - secondaryLoad(); - } - else - { - System.err.println("No log found; exiting."); - // System.exit(0); - - mode = LOG_NOT_SELECTED; - - logLoadComplete = false; - } - - // Schedule a job for the event-dispatching thread: - // creating and showing this application's GUI. - javax.swing.SwingUtilities.invokeLater(this); - } - } - - protected abstract LogPlaybackControlModel generateLogPlaybackControlModel( - LOG incomingLog); - - protected abstract View generateView(); - - protected abstract LogPlaybackControls generateLogPlaybackControls(); - - /** - * Translates the given file to XML. Necessary because it is not possible to cast directly to - * generic types. - * - * @param logToRead - * @return - * @throws SIMPLTranslationException - */ - protected abstract LOG translateXMLFromFile(File logToRead) throws SIMPLTranslationException; - - protected LOG readInXMLFile(File logToRead) - { - if (logToRead == null) - { - System.err.println("NO LOG TO READ!"); - return null; - } - - // read in the XML; this may take awhile - try - { - debug("READING LOG"); - - return translateXMLFromFile(logToRead); - } - catch (SIMPLTranslationException e) - { - System.err.println("READING LOG FAILED!"); - e.printStackTrace(); - - return null; - } - } - - protected JFileChooser createFileChooser() - { - JFileChooser fC = new JFileChooser(PropertiesAndDirectories.logDir()); - ExtensionFilter fF = new ExtensionFilter("xml"); - - fC.addChoosableFileFilter(fC.getAcceptAllFileFilter()); - fC.addChoosableFileFilter(fF); - - // find the most recent log file in the directory - - File[] logDirContents = PropertiesAndDirectories.logDir().listFiles(fF); - - if (logDirContents.length > 0) - { - File newestLog = logDirContents[0]; - - for (int i = 1; i < logDirContents.length; i++) - { - if (logDirContents[i].lastModified() > newestLog.lastModified()) - { - newestLog = logDirContents[i]; - } - } - - fC.setSelectedFile(newestLog); - } - - return fC; - } - - @Override - public void actionPerformed(ActionEvent e) - { - if (e.getActionCommand() == null) - { - if (playing && !this.controlsDisplay.isMousePressed()) - { - // advance the frame - log.forward(); - - if (this.playbackInterval == TIMESTAMP_PLAYBACK_INTERVAL) - { // if we're basing off the interval, we have to check some - // stuff - long delay = log.getNext().getSessionTime() - log.getCurrentOp().getSessionTime(); - - if (delay > 0) - { - t.setDelay((int) delay); - } - } - - if (log.getMaximum() <= log.getValue()) - { - this.fireActionEvent(new ActionEvent(this, 0, PAUSE)); - } - } - } - - if (PLAY.equals(e.getActionCommand())) - { - playing = true; - } - - if (PAUSE.equals(e.getActionCommand())) - { - playing = false; - } - - if (STOP.equals(e.getActionCommand())) - { - playing = false; - log.reset(); - } - - if (STEP_BACK.equals(e.getActionCommand())) - { - log.back(); - } - - if (STEP_FORWARD.equals(e.getActionCommand())) - { - log.forward(); - } - - if (logDisplay != null) - logDisplay.changeOp(log.getCurrentOp()); - - mainFrame.repaint(); - } - - public void addActionListener(ActionListener l) - { - actionListeners.add(l); - } - - protected void fireActionEvent(ActionEvent e) - { - for (ActionListener l : actionListeners) - { - l.actionPerformed(e); - } - } - - protected void showLogPlaybackGUI() - { - if (logDisplay != null) - logDisplay.load(this, log, log.getLogPrologue()); - - controlsDisplay = generateLogPlaybackControls(); - if (controlsDisplay != null) - { - controlsDisplay.setPreferredSize(new Dimension(800, 100)); - controlsDisplay.setMinimumSize(new Dimension(800, 100)); - controlsDisplay.setLoading(true); - - controlsDisplay.setLog(log); - controlsDisplay.setLoading(false); - - controlsDisplay.setupImportantEvents(); - } - - // logDisplay.setPreferredSize(new Dimension(800, 600)); - // logDisplay.setMinimumSize(new Dimension(800, 600)); - // logDisplay.setMaximumSize(new Dimension(800, 600)); - if (logDisplay != null) - logDisplay.invalidate(); - - mainFrame.getContentPane().removeAll(); - if (logDisplay != null) - mainFrame.getContentPane().add(logDisplay, BorderLayout.CENTER); - if (controlsDisplay != null) - mainFrame.getContentPane().add(controlsDisplay, BorderLayout.SOUTH); - - if (logDisplay != null && logDisplay.hasKeyListenerSubObject()) - { - mainFrame.addKeyListener(logDisplay.getKeyListenerSubObject()); - } - - if (logDisplay != null && logDisplay.hasActionListenerSubObject()) - { - t.addActionListener(logDisplay.getActionListenerSubObject()); - } - - mainFrame.invalidate(); - mainFrame.pack(); - mainFrame.setVisible(true); - - logLoadComplete = true; - } - - private void showLoadingGUI() - { - // logDisplay.setPreferredSize(new Dimension(800, 600)); - - if (logDisplay != null) - logDisplay.invalidate(); - } - - /** - * Creates the GUI for the log playback application. - */ - private void createGUI() - { - // JFrame.setDefaultLookAndFeelDecorated(true); - try - { - // Set cross-platform Java L&F (also called "Metal") - UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); - } - catch (UnsupportedLookAndFeelException e) - { - // handle exception - e.printStackTrace(); - } - catch (ClassNotFoundException e) - { - // handle exception - e.printStackTrace(); - } - catch (InstantiationException e) - { - // handle exception - e.printStackTrace(); - } - catch (IllegalAccessException e) - { - // handle exception - e.printStackTrace(); - } - - mainFrame = new JFrame(PropertiesAndDirectories.applicationName()); - mainFrame.addWindowListener(this); - - mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - // mainFrame.setBackground(Color.BLACK); - mainFrame.setPreferredSize(new Dimension(825, 875)); - mainFrame.setFocusable(true); - mainFrame.requestFocus(); - - mainFrame.getContentPane().setLayout(new BorderLayout()); - - logDisplay = this.generateView(); - - // mainFrame.getContentPane().add(logDisplay); - - mainFrame.validate(); - mainFrame.pack(); - mainFrame.setVisible(true); - } - - public void selectFile() - { - showFileSelectGUI(); - - mode = LOG_LOADING; - - javax.swing.SwingUtilities.invokeLater(this); - } - - public void showFileSelectGUI() - { - JFileChooser fC = this.createFileChooser(); - - int returnVal = fC.showOpenDialog(mainFrame); - - if (returnVal == JFileChooser.APPROVE_OPTION) - { // we now have a file...display a new GUI - logFile = fC.getSelectedFile(); - } - else - { // told to cancel; quitting - debug("No log selected; quitting."); - System.exit(0); - } - } - - protected void secondaryLoad() - { - } - - public void startAdjusting() - { - } - - /** - * Used to be thread safe with Swing. Either sets up the UI, or switches it, depending on whether - * or not a file has been selected. - * - * @see java.lang.Runnable#run() - */ - @Override - public void run() - { - if (!guiShown) - { - - debug("Showing GUI."); - this.createGUI(); - - guiShown = true; - } - - if (!logLoadComplete) - { - debug("mode is: " + mode); - - switch (mode) - { - case (LOG_NOT_SELECTED): - // no file selected - this.selectFile(); - break; - case (LOG_LOADING): - this.showLoadingGUI(); - break; - case (LOG_LOADED): - this.showLogPlaybackGUI(); - break; - } - } - } - - public void startProgram() - { - // Schedule a job for the event-dispatching thread: - // creating and showing this application's GUI. - javax.swing.SwingUtilities.invokeLater(this); - - t.start(); - } - - @Override - public void windowActivated(WindowEvent e) - { - } - - @Override - public void windowClosed(WindowEvent e) - { - t.stop(); - } - - /** - * Sends the server notification that we are logging-out, then shuts down the program. - */ - @Override - public void windowClosing(WindowEvent e) - { - } - - @Override - public void windowDeactivated(WindowEvent e) - { - } - - @Override - public void windowDeiconified(WindowEvent e) - { - t.start(); - } - - @Override - public void windowIconified(WindowEvent e) - { - t.stop(); - } - - @Override - public void windowOpened(WindowEvent e) - { - } - -} +package ecologylab.oodss.logging.playback; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.io.File; +import java.util.LinkedList; +import java.util.List; + +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.Timer; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import ecologylab.appframework.PropertiesAndDirectories; +import ecologylab.appframework.SingletonApplicationEnvironment; +import ecologylab.oodss.logging.Logging; +import ecologylab.oodss.logging.MixedInitiativeOp; +import ecologylab.oodss.logging.translationScope.MixedInitiativeOpClassesProvider; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; + +/** + * The main application for playing back log files. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public abstract class LogPlayer> extends + SingletonApplicationEnvironment implements ActionListener, WindowListener, PlaybackControlCommands, + Runnable +{ + private static final int LOG_LOADED = 2; + + private static final int LOG_LOADING = 1; + + private static final int LOG_NOT_SELECTED = 0; + + private List actionListeners = new LinkedList(); + + protected LogPlaybackControls controlsDisplay = null; + + protected View logDisplay = null; + + protected LogPlaybackControlModel log; + + protected File logFile = null; + + protected JFrame mainFrame; + + protected boolean playing = false; + + protected Timer t; + + /** + * Modes: 0 = no file selected (need to get a file name). 1 = file selected and loading. 2 = file + * loaded, display log. + */ + + protected int mode = LOG_NOT_SELECTED; + + private boolean guiShown; + + protected SimplTypesScope translationScope; + + public final static int DEFAULT_PLAYBACK_INTERVAL = 100; + + public final static int TIMESTAMP_PLAYBACK_INTERVAL = -1; + + /** + * The number of milliseconds between ops when the log is playing. Setting to -1 will try to use + * op timestamps. + */ + protected int playbackInterval = DEFAULT_PLAYBACK_INTERVAL; + + private boolean logLoadComplete = false; + + /** + * + * @param appName + * @param args + * @param translationScope + * @param opSubclasses + * An array of subclasses of MixedInitiativeOp that will be used to translate the + * operations read in by the player. + * @throws SIMPLTranslationException + */ + public LogPlayer(String appName, String[] args, SimplTypesScope translationScope, + Class[] opSubclasses) throws SIMPLTranslationException + { + super(appName, translationScope, (SimplTypesScope) null, args, 0); + + // create a translation scope for the opSubclasses + if (opSubclasses == null) + opSubclasses = MixedInitiativeOpClassesProvider.STATIC_INSTANCE.provideClasses(); + + SimplTypesScope.get(Logging.MIXED_INITIATIVE_OP_TRANSLATION_SCOPE, opSubclasses); + + guiShown = false; + + if (translationScope != null) + this.translationScope = translationScope; + else + this.translationScope = SimplTypesScope.get(Logging.MIXED_INITIATIVE_OP_TRANSLATION_SCOPE); + + LOG incomingLog = null; + + // see if a log file has been specified + if (args.length > 1) + { // a log was specified + debug("Getting log file from args!"); + logFile = new File(args[1]); + mode = LOG_LOADING; + + logLoadComplete = false; + } + + while (incomingLog == null) + { + // Schedule a job for the event-dispatching thread: + // creating and showing this application's GUI. + javax.swing.SwingUtilities.invokeLater(this); + + while (mode != LOG_LOADING || logFile == null) + { // wait until we get a logFile or until the program quits + try + { + Thread.sleep(100); + } + catch (InterruptedException e) + { + e.printStackTrace(); + } + } + + // by now, incomingLog must have something + debug("Reading log from file: " + logFile); + + // Schedule a job for the event-dispatching thread: + // creating and showing this application's GUI. + javax.swing.SwingUtilities.invokeLater(this); + + incomingLog = this.readInXMLFile(logFile); + + if (incomingLog != null) + { + this.log = generateLogPlaybackControlModel(incomingLog); + + t = new Timer(this.playbackInterval, this); + + mode = LOG_LOADED; + + secondaryLoad(); + } + else + { + System.err.println("No log found; exiting."); + // System.exit(0); + + mode = LOG_NOT_SELECTED; + + logLoadComplete = false; + } + + // Schedule a job for the event-dispatching thread: + // creating and showing this application's GUI. + javax.swing.SwingUtilities.invokeLater(this); + } + } + + protected abstract LogPlaybackControlModel generateLogPlaybackControlModel( + LOG incomingLog); + + protected abstract View generateView(); + + protected abstract LogPlaybackControls generateLogPlaybackControls(); + + /** + * Translates the given file to XML. Necessary because it is not possible to cast directly to + * generic types. + * + * @param logToRead + * @return + * @throws SIMPLTranslationException + */ + protected abstract LOG translateXMLFromFile(File logToRead) throws SIMPLTranslationException; + + protected LOG readInXMLFile(File logToRead) + { + if (logToRead == null) + { + System.err.println("NO LOG TO READ!"); + return null; + } + + // read in the XML; this may take awhile + try + { + debug("READING LOG"); + + return translateXMLFromFile(logToRead); + } + catch (SIMPLTranslationException e) + { + System.err.println("READING LOG FAILED!"); + e.printStackTrace(); + + return null; + } + } + + protected JFileChooser createFileChooser() + { + JFileChooser fC = new JFileChooser(PropertiesAndDirectories.logDir()); + ExtensionFilter fF = new ExtensionFilter("xml"); + + fC.addChoosableFileFilter(fC.getAcceptAllFileFilter()); + fC.addChoosableFileFilter(fF); + + // find the most recent log file in the directory + + File[] logDirContents = PropertiesAndDirectories.logDir().listFiles(fF); + + if (logDirContents.length > 0) + { + File newestLog = logDirContents[0]; + + for (int i = 1; i < logDirContents.length; i++) + { + if (logDirContents[i].lastModified() > newestLog.lastModified()) + { + newestLog = logDirContents[i]; + } + } + + fC.setSelectedFile(newestLog); + } + + return fC; + } + + @Override + public void actionPerformed(ActionEvent e) + { + if (e.getActionCommand() == null) + { + if (playing && !this.controlsDisplay.isMousePressed()) + { + // advance the frame + log.forward(); + + if (this.playbackInterval == TIMESTAMP_PLAYBACK_INTERVAL) + { // if we're basing off the interval, we have to check some + // stuff + long delay = log.getNext().getSessionTime() - log.getCurrentOp().getSessionTime(); + + if (delay > 0) + { + t.setDelay((int) delay); + } + } + + if (log.getMaximum() <= log.getValue()) + { + this.fireActionEvent(new ActionEvent(this, 0, PAUSE)); + } + } + } + + if (PLAY.equals(e.getActionCommand())) + { + playing = true; + } + + if (PAUSE.equals(e.getActionCommand())) + { + playing = false; + } + + if (STOP.equals(e.getActionCommand())) + { + playing = false; + log.reset(); + } + + if (STEP_BACK.equals(e.getActionCommand())) + { + log.back(); + } + + if (STEP_FORWARD.equals(e.getActionCommand())) + { + log.forward(); + } + + if (logDisplay != null) + logDisplay.changeOp(log.getCurrentOp()); + + mainFrame.repaint(); + } + + public void addActionListener(ActionListener l) + { + actionListeners.add(l); + } + + protected void fireActionEvent(ActionEvent e) + { + for (ActionListener l : actionListeners) + { + l.actionPerformed(e); + } + } + + protected void showLogPlaybackGUI() + { + if (logDisplay != null) + logDisplay.load(this, log, log.getLogPrologue()); + + controlsDisplay = generateLogPlaybackControls(); + if (controlsDisplay != null) + { + controlsDisplay.setPreferredSize(new Dimension(800, 100)); + controlsDisplay.setMinimumSize(new Dimension(800, 100)); + controlsDisplay.setLoading(true); + + controlsDisplay.setLog(log); + controlsDisplay.setLoading(false); + + controlsDisplay.setupImportantEvents(); + } + + // logDisplay.setPreferredSize(new Dimension(800, 600)); + // logDisplay.setMinimumSize(new Dimension(800, 600)); + // logDisplay.setMaximumSize(new Dimension(800, 600)); + if (logDisplay != null) + logDisplay.invalidate(); + + mainFrame.getContentPane().removeAll(); + if (logDisplay != null) + mainFrame.getContentPane().add(logDisplay, BorderLayout.CENTER); + if (controlsDisplay != null) + mainFrame.getContentPane().add(controlsDisplay, BorderLayout.SOUTH); + + if (logDisplay != null && logDisplay.hasKeyListenerSubObject()) + { + mainFrame.addKeyListener(logDisplay.getKeyListenerSubObject()); + } + + if (logDisplay != null && logDisplay.hasActionListenerSubObject()) + { + t.addActionListener(logDisplay.getActionListenerSubObject()); + } + + mainFrame.invalidate(); + mainFrame.pack(); + mainFrame.setVisible(true); + + logLoadComplete = true; + } + + private void showLoadingGUI() + { + // logDisplay.setPreferredSize(new Dimension(800, 600)); + + if (logDisplay != null) + logDisplay.invalidate(); + } + + /** + * Creates the GUI for the log playback application. + */ + private void createGUI() + { + // JFrame.setDefaultLookAndFeelDecorated(true); + try + { + // Set cross-platform Java L&F (also called "Metal") + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + } + catch (UnsupportedLookAndFeelException e) + { + // handle exception + e.printStackTrace(); + } + catch (ClassNotFoundException e) + { + // handle exception + e.printStackTrace(); + } + catch (InstantiationException e) + { + // handle exception + e.printStackTrace(); + } + catch (IllegalAccessException e) + { + // handle exception + e.printStackTrace(); + } + + mainFrame = new JFrame(PropertiesAndDirectories.applicationName()); + mainFrame.addWindowListener(this); + + mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + // mainFrame.setBackground(Color.BLACK); + mainFrame.setPreferredSize(new Dimension(825, 875)); + mainFrame.setFocusable(true); + mainFrame.requestFocus(); + + mainFrame.getContentPane().setLayout(new BorderLayout()); + + logDisplay = this.generateView(); + + // mainFrame.getContentPane().add(logDisplay); + + mainFrame.validate(); + mainFrame.pack(); + mainFrame.setVisible(true); + } + + public void selectFile() + { + showFileSelectGUI(); + + mode = LOG_LOADING; + + javax.swing.SwingUtilities.invokeLater(this); + } + + public void showFileSelectGUI() + { + JFileChooser fC = this.createFileChooser(); + + int returnVal = fC.showOpenDialog(mainFrame); + + if (returnVal == JFileChooser.APPROVE_OPTION) + { // we now have a file...display a new GUI + logFile = fC.getSelectedFile(); + } + else + { // told to cancel; quitting + debug("No log selected; quitting."); + System.exit(0); + } + } + + protected void secondaryLoad() + { + } + + public void startAdjusting() + { + } + + /** + * Used to be thread safe with Swing. Either sets up the UI, or switches it, depending on whether + * or not a file has been selected. + * + * @see java.lang.Runnable#run() + */ + @Override + public void run() + { + if (!guiShown) + { + + debug("Showing GUI."); + this.createGUI(); + + guiShown = true; + } + + if (!logLoadComplete) + { + debug("mode is: " + mode); + + switch (mode) + { + case (LOG_NOT_SELECTED): + // no file selected + this.selectFile(); + break; + case (LOG_LOADING): + this.showLoadingGUI(); + break; + case (LOG_LOADED): + this.showLogPlaybackGUI(); + break; + } + } + } + + public void startProgram() + { + // Schedule a job for the event-dispatching thread: + // creating and showing this application's GUI. + javax.swing.SwingUtilities.invokeLater(this); + + t.start(); + } + + @Override + public void windowActivated(WindowEvent e) + { + } + + @Override + public void windowClosed(WindowEvent e) + { + t.stop(); + } + + /** + * Sends the server notification that we are logging-out, then shuts down the program. + */ + @Override + public void windowClosing(WindowEvent e) + { + } + + @Override + public void windowDeactivated(WindowEvent e) + { + } + + @Override + public void windowDeiconified(WindowEvent e) + { + t.start(); + } + + @Override + public void windowIconified(WindowEvent e) + { + t.stop(); + } + + @Override + public void windowOpened(WindowEvent e) + { + } + +} diff --git a/simplCore/src/ecologylab/oodss/logging/playback/PlaybackControlCommands.java b/simplCore/src/ecologylab/oodss/logging/playback/PlaybackControlCommands.java index 6f42c646..0fad716c 100755 --- a/simplCore/src/ecologylab/oodss/logging/playback/PlaybackControlCommands.java +++ b/simplCore/src/ecologylab/oodss/logging/playback/PlaybackControlCommands.java @@ -1,20 +1,20 @@ -package ecologylab.oodss.logging.playback; - -/** - * Status indicators for log playback application. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public interface PlaybackControlCommands -{ - static final String PLAY = "play"; - - static final String STOP = "stop"; - - static final String PAUSE = "pause"; - - static final String STEP_FORWARD = "stepForward"; - - static final String STEP_BACK = "stepBack"; -} +package ecologylab.oodss.logging.playback; + +/** + * Status indicators for log playback application. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public interface PlaybackControlCommands +{ + static final String PLAY = "play"; + + static final String STOP = "stop"; + + static final String PAUSE = "pause"; + + static final String STEP_FORWARD = "stepForward"; + + static final String STEP_BACK = "stepBack"; +} diff --git a/simplCore/src/ecologylab/oodss/logging/playback/View.java b/simplCore/src/ecologylab/oodss/logging/playback/View.java index 99ef1cb1..883cf52a 100644 --- a/simplCore/src/ecologylab/oodss/logging/playback/View.java +++ b/simplCore/src/ecologylab/oodss/logging/playback/View.java @@ -1,132 +1,132 @@ -/* - * Created on Apr 13, 2007 - */ -package ecologylab.oodss.logging.playback; - -import java.awt.Color; -import java.awt.Graphics; -import java.awt.event.ActionListener; -import java.awt.event.KeyListener; - -import javax.swing.BoxLayout; -import javax.swing.JPanel; - -import ecologylab.oodss.logging.MixedInitiativeOp; -import ecologylab.oodss.logging.Prologue; - -/** - * Abstract class for displaying logged operations. Subclasses provide specific visualization of log - * ops. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - * @param - */ -public abstract class View extends JPanel -{ - protected T currentOp; - - protected Prologue prologue; - - protected boolean loaded = false; - - public View() - { - this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); - } - - /** - * @see javax.swing.JComponent#paintComponent(java.awt.Graphics) - */ - @Override - protected void paintComponent(Graphics arg0) - { - if (loaded) - this.render(arg0); - else - this.renderLoading(arg0); - } - - protected void load(LogPlayer player, LogPlaybackControlModel log, Prologue prologue) - { - if (!loaded) - { - this.prologue = prologue; - - this.currentOp = (T) log.getCurrentOp(); - - this.loaded = true; - } - } - - protected abstract void render(Graphics g); - - protected void renderLoading(Graphics g) - { - g.fillRect(0, 0, this.getWidth(), this.getHeight()); - - g.setColor(Color.BLACK); - - g.drawString("No log file loaded.", 10, 10); - } - - public void setLoaded(boolean loaded) - { - this.loaded = loaded; - } - - public void changeOp(T newOp) - { - this.currentOp = newOp; - this.repaint(); - } - - /** - * Indicates whether or not this View has a KeyListener object. - * - * @return - */ - public boolean hasKeyListenerSubObject() - { - return false; - } - - /** - * If this View contains a KeyListener object (for example, to enable some sort of keyboard - * interaction with the log frame); this method returns it. - * - * If hasKeyListener() returns true, then this method must return a KeyListener object; otherwise, - * it should return null. - * - * @return - */ - public KeyListener getKeyListenerSubObject() - { - return null; - } - - /** - * Indicates whether or not this View has an ActionListener object. - * - * @return - */ - public boolean hasActionListenerSubObject() - { - return false; - } - - /** - * If this View contains a ActionListener object (for example, to enable some sort of interaction - * with the log frame); this method returns it. - * - * If hasActionListener() returns true, then this method must return a KeyListener object; - * otherwise, it should return null. - * - * @return - */ - public ActionListener getActionListenerSubObject() - { - return null; - } - -} +/* + * Created on Apr 13, 2007 + */ +package ecologylab.oodss.logging.playback; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.event.ActionListener; +import java.awt.event.KeyListener; + +import javax.swing.BoxLayout; +import javax.swing.JPanel; + +import ecologylab.oodss.logging.MixedInitiativeOp; +import ecologylab.oodss.logging.Prologue; + +/** + * Abstract class for displaying logged operations. Subclasses provide specific visualization of log + * ops. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + * @param + */ +public abstract class View extends JPanel +{ + protected T currentOp; + + protected Prologue prologue; + + protected boolean loaded = false; + + public View() + { + this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); + } + + /** + * @see javax.swing.JComponent#paintComponent(java.awt.Graphics) + */ + @Override + protected void paintComponent(Graphics arg0) + { + if (loaded) + this.render(arg0); + else + this.renderLoading(arg0); + } + + protected void load(LogPlayer player, LogPlaybackControlModel log, Prologue prologue) + { + if (!loaded) + { + this.prologue = prologue; + + this.currentOp = (T) log.getCurrentOp(); + + this.loaded = true; + } + } + + protected abstract void render(Graphics g); + + protected void renderLoading(Graphics g) + { + g.fillRect(0, 0, this.getWidth(), this.getHeight()); + + g.setColor(Color.BLACK); + + g.drawString("No log file loaded.", 10, 10); + } + + public void setLoaded(boolean loaded) + { + this.loaded = loaded; + } + + public void changeOp(T newOp) + { + this.currentOp = newOp; + this.repaint(); + } + + /** + * Indicates whether or not this View has a KeyListener object. + * + * @return + */ + public boolean hasKeyListenerSubObject() + { + return false; + } + + /** + * If this View contains a KeyListener object (for example, to enable some sort of keyboard + * interaction with the log frame); this method returns it. + * + * If hasKeyListener() returns true, then this method must return a KeyListener object; otherwise, + * it should return null. + * + * @return + */ + public KeyListener getKeyListenerSubObject() + { + return null; + } + + /** + * Indicates whether or not this View has an ActionListener object. + * + * @return + */ + public boolean hasActionListenerSubObject() + { + return false; + } + + /** + * If this View contains a ActionListener object (for example, to enable some sort of interaction + * with the log frame); this method returns it. + * + * If hasActionListener() returns true, then this method must return a KeyListener object; + * otherwise, it should return null. + * + * @return + */ + public ActionListener getActionListenerSubObject() + { + return null; + } + +} diff --git a/simplCore/src/ecologylab/oodss/logging/playback/package.html b/simplCore/src/ecologylab/oodss/logging/playback/package.html index f340c8dd..b8be3707 100644 --- a/simplCore/src/ecologylab/oodss/logging/playback/package.html +++ b/simplCore/src/ecologylab/oodss/logging/playback/package.html @@ -1,3 +1,3 @@ - -Program elements for building log playback applications. - + +Program elements for building log playback applications. + diff --git a/simplCore/src/ecologylab/oodss/logging/translationScope/LoggingTranslationsProvider.java b/simplCore/src/ecologylab/oodss/logging/translationScope/LoggingTranslationsProvider.java index 21163f04..c087a662 100644 --- a/simplCore/src/ecologylab/oodss/logging/translationScope/LoggingTranslationsProvider.java +++ b/simplCore/src/ecologylab/oodss/logging/translationScope/LoggingTranslationsProvider.java @@ -1,42 +1,42 @@ -package ecologylab.oodss.logging.translationScope; - -import ecologylab.oodss.logging.Epilogue; -import ecologylab.oodss.logging.LogEvent; -import ecologylab.oodss.logging.LogOps; -import ecologylab.oodss.logging.Logging; -import ecologylab.oodss.logging.LogueMessage; -import ecologylab.oodss.logging.Prologue; -import ecologylab.oodss.logging.SendEpilogue; -import ecologylab.oodss.logging.SendPrologue; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.types.element.ElementTypeTranslationsProvider; - -/** - * Provide XML translation for logging basics. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class LoggingTranslationsProvider -{ - public static final String LOGGING_TRANSLATION_SCOPE = "LOGGING_TRANSLATION_SCOPE"; - - private static final SimplTypesScope[] OTHER_TRANSLATION_SCOPES = - { ElementTypeTranslationsProvider - .get() }; - - public static final Class TRANSLATIONS[] = - { Logging.class, LogOps.class, - LogEvent.class, LogueMessage.class, Prologue.class, SendEpilogue.class, SendPrologue.class, - Epilogue.class }; - - /** - * This accessor will work from anywhere, in any order, and stay efficient. - * - * @return TranslationSpace for basic ecologylab.oodss - */ - public static SimplTypesScope get() - { - return SimplTypesScope.get(LOGGING_TRANSLATION_SCOPE, OTHER_TRANSLATION_SCOPES, TRANSLATIONS, - MixedInitiativeOpClassesProvider.STATIC_INSTANCE.provideClasses()); - } -} +package ecologylab.oodss.logging.translationScope; + +import ecologylab.oodss.logging.Epilogue; +import ecologylab.oodss.logging.LogEvent; +import ecologylab.oodss.logging.LogOps; +import ecologylab.oodss.logging.Logging; +import ecologylab.oodss.logging.LogueMessage; +import ecologylab.oodss.logging.Prologue; +import ecologylab.oodss.logging.SendEpilogue; +import ecologylab.oodss.logging.SendPrologue; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.types.element.ElementTypeTranslationsProvider; + +/** + * Provide XML translation for logging basics. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class LoggingTranslationsProvider +{ + public static final String LOGGING_TRANSLATION_SCOPE = "LOGGING_TRANSLATION_SCOPE"; + + private static final SimplTypesScope[] OTHER_TRANSLATION_SCOPES = + { ElementTypeTranslationsProvider + .get() }; + + public static final Class TRANSLATIONS[] = + { Logging.class, LogOps.class, + LogEvent.class, LogueMessage.class, Prologue.class, SendEpilogue.class, SendPrologue.class, + Epilogue.class }; + + /** + * This accessor will work from anywhere, in any order, and stay efficient. + * + * @return TranslationSpace for basic ecologylab.oodss + */ + public static SimplTypesScope get() + { + return SimplTypesScope.get(LOGGING_TRANSLATION_SCOPE, OTHER_TRANSLATION_SCOPES, TRANSLATIONS, + MixedInitiativeOpClassesProvider.STATIC_INSTANCE.provideClasses()); + } +} diff --git a/simplCore/src/ecologylab/oodss/logging/translationScope/MixedInitiativeOpClassesProvider.java b/simplCore/src/ecologylab/oodss/logging/translationScope/MixedInitiativeOpClassesProvider.java index baacceb4..0e30b201 100644 --- a/simplCore/src/ecologylab/oodss/logging/translationScope/MixedInitiativeOpClassesProvider.java +++ b/simplCore/src/ecologylab/oodss/logging/translationScope/MixedInitiativeOpClassesProvider.java @@ -1,31 +1,31 @@ -package ecologylab.oodss.logging.translationScope; - -import ecologylab.oodss.logging.MixedInitiativeOp; -import ecologylab.serialization.TranslationsClassProvider; - -/** - * Provide base log operation classes for translating a polymorphic list of Ops. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class MixedInitiativeOpClassesProvider extends TranslationsClassProvider -{ - public static final MixedInitiativeOpClassesProvider STATIC_INSTANCE = new MixedInitiativeOpClassesProvider(); - - protected MixedInitiativeOpClassesProvider() - { - - } - - /** - * @see ecologylab.serialization.TranslationsClassProvider#specificSuppliedClasses() - */ - @Override - protected Class[] specificSuppliedClasses() - { - Class mixedInitiativeOpClasses[] = - { MixedInitiativeOp.class }; - - return mixedInitiativeOpClasses; - } -} +package ecologylab.oodss.logging.translationScope; + +import ecologylab.oodss.logging.MixedInitiativeOp; +import ecologylab.serialization.TranslationsClassProvider; + +/** + * Provide base log operation classes for translating a polymorphic list of Ops. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class MixedInitiativeOpClassesProvider extends TranslationsClassProvider +{ + public static final MixedInitiativeOpClassesProvider STATIC_INSTANCE = new MixedInitiativeOpClassesProvider(); + + protected MixedInitiativeOpClassesProvider() + { + + } + + /** + * @see ecologylab.serialization.TranslationsClassProvider#specificSuppliedClasses() + */ + @Override + protected Class[] specificSuppliedClasses() + { + Class mixedInitiativeOpClasses[] = + { MixedInitiativeOp.class }; + + return mixedInitiativeOpClasses; + } +} diff --git a/simplCore/src/ecologylab/oodss/messages/BadSemanticContentResponse.java b/simplCore/src/ecologylab/oodss/messages/BadSemanticContentResponse.java index 87d497c1..07697ce8 100644 --- a/simplCore/src/ecologylab/oodss/messages/BadSemanticContentResponse.java +++ b/simplCore/src/ecologylab/oodss/messages/BadSemanticContentResponse.java @@ -1,27 +1,27 @@ -package ecologylab.oodss.messages; - -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * The ResponseMessage send from server to client when the RequestMessage - * is well-formed, but doesn't make sense in the current context. - * - * @author andruid - * @author blake - * @author eunyee - */ -@simpl_inherit -public class BadSemanticContentResponse extends ErrorResponse -{ - - public BadSemanticContentResponse() - { - super(); - } - - public BadSemanticContentResponse(String response) - { - super(response); - } - -} +package ecologylab.oodss.messages; + +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * The ResponseMessage send from server to client when the RequestMessage + * is well-formed, but doesn't make sense in the current context. + * + * @author andruid + * @author blake + * @author eunyee + */ +@simpl_inherit +public class BadSemanticContentResponse extends ErrorResponse +{ + + public BadSemanticContentResponse() + { + super(); + } + + public BadSemanticContentResponse(String response) + { + super(response); + } + +} diff --git a/simplCore/src/ecologylab/oodss/messages/CfCollaborationGetSurrogate.java b/simplCore/src/ecologylab/oodss/messages/CfCollaborationGetSurrogate.java index 469736a2..31fb9d5f 100644 --- a/simplCore/src/ecologylab/oodss/messages/CfCollaborationGetSurrogate.java +++ b/simplCore/src/ecologylab/oodss/messages/CfCollaborationGetSurrogate.java @@ -1,57 +1,57 @@ -package ecologylab.oodss.messages; - - -import ecologylab.collections.Scope; -import ecologylab.generic.Debug; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -@simpl_inherit -public class CfCollaborationGetSurrogate extends RequestMessage { - - @simpl_scalar @simpl_hints(Hint.XML_LEAF_CDATA) protected String surrogateSetString; - - SimplTypesScope translationScope; - - public CfCollaborationGetSurrogate() - { - super(); - } - - public String getSurrogateSetString() - { - return surrogateSetString; - } - - public void setSurrogateSetString(String surrogateSetString) - { - this.surrogateSetString = surrogateSetString; - } - - @Override - public ResponseMessage performService(Scope objectRegistry) - { - Debug.println("Received loud and clear: " + surrogateSetString); - - return OkResponse.get(); - } - - public CfCollaborationGetSurrogate (String surrogateSetString, SimplTypesScope translationScope) - throws SIMPLTranslationException - { - this(surrogateSetString); - this.translationScope = translationScope; - } - - public CfCollaborationGetSurrogate(String surrogateSetString) - { - super(); - this.surrogateSetString = surrogateSetString; - } - - -} +package ecologylab.oodss.messages; + + +import ecologylab.collections.Scope; +import ecologylab.generic.Debug; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +@simpl_inherit +public class CfCollaborationGetSurrogate extends RequestMessage { + + @simpl_scalar @simpl_hints(Hint.XML_LEAF_CDATA) protected String surrogateSetString; + + SimplTypesScope translationScope; + + public CfCollaborationGetSurrogate() + { + super(); + } + + public String getSurrogateSetString() + { + return surrogateSetString; + } + + public void setSurrogateSetString(String surrogateSetString) + { + this.surrogateSetString = surrogateSetString; + } + + @Override + public ResponseMessage performService(Scope objectRegistry) + { + Debug.println("Received loud and clear: " + surrogateSetString); + + return OkResponse.get(); + } + + public CfCollaborationGetSurrogate (String surrogateSetString, SimplTypesScope translationScope) + throws SIMPLTranslationException + { + this(surrogateSetString); + this.translationScope = translationScope; + } + + public CfCollaborationGetSurrogate(String surrogateSetString) + { + super(); + this.surrogateSetString = surrogateSetString; + } + + +} diff --git a/simplCore/src/ecologylab/oodss/messages/CloseMessage.java b/simplCore/src/ecologylab/oodss/messages/CloseMessage.java index a886579c..a5c12695 100644 --- a/simplCore/src/ecologylab/oodss/messages/CloseMessage.java +++ b/simplCore/src/ecologylab/oodss/messages/CloseMessage.java @@ -1,21 +1,21 @@ -package ecologylab.oodss.messages; - -import ecologylab.collections.Scope; -import ecologylab.serialization.annotations.simpl_inherit; - -@simpl_inherit public class CloseMessage extends RequestMessage -{ - private static final CloseMessage INSTANCE = new CloseMessage(); - - @Override public ResponseMessage performService(Scope objectRegistry) - { - System.exit(0); - return null; - } - - public static CloseMessage get() - { - return INSTANCE; - } - -} +package ecologylab.oodss.messages; + +import ecologylab.collections.Scope; +import ecologylab.serialization.annotations.simpl_inherit; + +@simpl_inherit public class CloseMessage extends RequestMessage +{ + private static final CloseMessage INSTANCE = new CloseMessage(); + + @Override public ResponseMessage performService(Scope objectRegistry) + { + System.exit(0); + return null; + } + + public static CloseMessage get() + { + return INSTANCE; + } + +} diff --git a/simplCore/src/ecologylab/oodss/messages/ContinuedHTTPGetRequest.java b/simplCore/src/ecologylab/oodss/messages/ContinuedHTTPGetRequest.java index 3c231caf..cde877b0 100644 --- a/simplCore/src/ecologylab/oodss/messages/ContinuedHTTPGetRequest.java +++ b/simplCore/src/ecologylab/oodss/messages/ContinuedHTTPGetRequest.java @@ -1,42 +1,42 @@ -package ecologylab.oodss.messages; - -import java.util.Hashtable; - -import ecologylab.collections.Scope; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -@simpl_inherit -public class ContinuedHTTPGetRequest extends HttpRequest -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF_CDATA) String messageFragment; - - @simpl_scalar boolean isLast; - - static final Hashtable partialMessages = new Hashtable(); - - public ContinuedHTTPGetRequest() - { - super(); - } - - @Override - public ResponseMessage performService(Scope objectRegistry) - { - if (!isLast) - { - // concatenate fragments into Hashtable entry. for now, key is IP number - // in a later revision, key may be a UID we generate and pass back to the caller - } - else - { - // concatenate latest messageFragment with enty in the Hashtable for this IP number - - // translate this String into XML and call performService(). - } - return OkResponse.get(); - } - -} +package ecologylab.oodss.messages; + +import java.util.Hashtable; + +import ecologylab.collections.Scope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +@simpl_inherit +public class ContinuedHTTPGetRequest extends HttpRequest +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF_CDATA) String messageFragment; + + @simpl_scalar boolean isLast; + + static final Hashtable partialMessages = new Hashtable(); + + public ContinuedHTTPGetRequest() + { + super(); + } + + @Override + public ResponseMessage performService(Scope objectRegistry) + { + if (!isLast) + { + // concatenate fragments into Hashtable entry. for now, key is IP number + // in a later revision, key may be a UID we generate and pass back to the caller + } + else + { + // concatenate latest messageFragment with enty in the Hashtable for this IP number + + // translate this String into XML and call performService(). + } + return OkResponse.get(); + } + +} diff --git a/simplCore/src/ecologylab/oodss/messages/DefaultServicesTranslations.java b/simplCore/src/ecologylab/oodss/messages/DefaultServicesTranslations.java index 7cf860b0..40a857aa 100644 --- a/simplCore/src/ecologylab/oodss/messages/DefaultServicesTranslations.java +++ b/simplCore/src/ecologylab/oodss/messages/DefaultServicesTranslations.java @@ -1,46 +1,46 @@ -package ecologylab.oodss.messages; - -import ecologylab.oodss.logging.Epilogue; -import ecologylab.oodss.logging.LogOps; -import ecologylab.oodss.logging.Prologue; -import ecologylab.oodss.logging.SendEpilogue; -import ecologylab.oodss.logging.SendPrologue; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.types.element.ElementTypeTranslationsProvider; - -/** - * Provide XML translation mappings for use in processing CF services requests. - * - * @author andruid - */ -public class DefaultServicesTranslations -{ - public static final String PACKAGE_NAME = "ecologylab.oodss.messages"; - - public static final Class TRANSLATIONS[] = - { RequestMessage.class, ResponseMessage.class, - CloseMessage.class, - - OkResponse.class, BadSemanticContentResponse.class, ErrorResponse.class, - - Prologue.class, Epilogue.class, LogOps.class, SendEpilogue.class, SendPrologue.class, - - HttpRequest.class, HttpGetRequest.class, PingRequest.class, Ping.class, Pong.class, - UrlMessage.class, - - CfCollaborationGetSurrogate.class, ContinuedHTTPGetRequest.class, IgnoreRequest.class, - - InitConnectionRequest.class, InitConnectionResponse.class, DisconnectRequest.class, - - ServiceMessage.class, UrlMessage.class, UpdateMessage.class }; - - /** - * This accessor will work from anywhere, in any order, and stay efficient. - * - * @return TranslationSpace for basic ecologylab.oodss - */ - public static SimplTypesScope get() - { - return SimplTypesScope.get(PACKAGE_NAME, ElementTypeTranslationsProvider.get(), TRANSLATIONS); - } -} +package ecologylab.oodss.messages; + +import ecologylab.oodss.logging.Epilogue; +import ecologylab.oodss.logging.LogOps; +import ecologylab.oodss.logging.Prologue; +import ecologylab.oodss.logging.SendEpilogue; +import ecologylab.oodss.logging.SendPrologue; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.types.element.ElementTypeTranslationsProvider; + +/** + * Provide XML translation mappings for use in processing CF services requests. + * + * @author andruid + */ +public class DefaultServicesTranslations +{ + public static final String PACKAGE_NAME = "ecologylab.oodss.messages"; + + public static final Class TRANSLATIONS[] = + { RequestMessage.class, ResponseMessage.class, + CloseMessage.class, + + OkResponse.class, BadSemanticContentResponse.class, ErrorResponse.class, + + Prologue.class, Epilogue.class, LogOps.class, SendEpilogue.class, SendPrologue.class, + + HttpRequest.class, HttpGetRequest.class, PingRequest.class, Ping.class, Pong.class, + UrlMessage.class, + + CfCollaborationGetSurrogate.class, ContinuedHTTPGetRequest.class, IgnoreRequest.class, + + InitConnectionRequest.class, InitConnectionResponse.class, DisconnectRequest.class, + + ServiceMessage.class, UrlMessage.class, UpdateMessage.class }; + + /** + * This accessor will work from anywhere, in any order, and stay efficient. + * + * @return TranslationSpace for basic ecologylab.oodss + */ + public static SimplTypesScope get() + { + return SimplTypesScope.get(PACKAGE_NAME, ElementTypeTranslationsProvider.get(), TRANSLATIONS); + } +} diff --git a/simplCore/src/ecologylab/oodss/messages/DisconnectRequest.java b/simplCore/src/ecologylab/oodss/messages/DisconnectRequest.java index 3896b91c..61c7033b 100644 --- a/simplCore/src/ecologylab/oodss/messages/DisconnectRequest.java +++ b/simplCore/src/ecologylab/oodss/messages/DisconnectRequest.java @@ -1,92 +1,92 @@ -/** - * - */ -package ecologylab.oodss.messages; - -import java.io.IOException; -import java.net.BindException; -import java.net.InetAddress; -import java.net.UnknownHostException; - -import ecologylab.collections.Scope; -import ecologylab.oodss.distributed.client.NIOClient; -import ecologylab.oodss.distributed.common.SessionObjects; -import ecologylab.oodss.distributed.exception.MessageTooLargeException; -import ecologylab.oodss.distributed.server.DoubleThreadedNIOServer; -import ecologylab.oodss.distributed.server.clientsessionmanager.SessionHandle; -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * A request that indicates that the client wishes to be permanently disconnected from the server. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_inherit -public class DisconnectRequest extends RequestMessage -{ - public static final DisconnectRequest REUSABLE_INSTANCE = new DisconnectRequest(); - - /** - * - */ - public DisconnectRequest() - { - super(); - } - - /** - * @see ecologylab.oodss.messages.RequestMessage#performService(ecologylab.collections.Scope) - */ - @Override - public ResponseMessage performService(SCOPE localScope) - { - debug("**** running disconnect request ****"); - - SessionHandle handle = (SessionHandle) localScope.get(SessionObjects.SESSION_HANDLE); - - if (handle != null) - handle.invalidate(); - - return OkResponse.reusableInstance; - } - - public static void main(String[] args) throws BindException, UnknownHostException, IOException, - MessageTooLargeException - { - DoubleThreadedNIOServer server = DoubleThreadedNIOServer.getInstance( 10000, - InetAddress.getLocalHost(), - DefaultServicesTranslations.get(), - new Scope(), - 9999, - 99999); - - server.start(); - - System.err.println("c1 instantiate"); - NIOClient c1 = new NIOClient( "128.194.147.181", - 10000, - DefaultServicesTranslations.get(), - new Scope()); - - System.err.println("c1 connect"); - c1.connect(); - - System.err.println("c2 instantiate"); - NIOClient c2 = new NIOClient( "128.194.147.181", - 10000, - DefaultServicesTranslations.get(), - new Scope()); - - System.err.println("c2 connect"); - c2.connect(); - - System.err.println("c1 disconnect"); - c1.sendMessage(new DisconnectRequest()); - - System.err.println("c2 disconnect"); - c2.sendMessage(new DisconnectRequest()); - - System.err.println("c1 disconnect again"); - c1.sendMessage(new DisconnectRequest()); - } -} +/** + * + */ +package ecologylab.oodss.messages; + +import java.io.IOException; +import java.net.BindException; +import java.net.InetAddress; +import java.net.UnknownHostException; + +import ecologylab.collections.Scope; +import ecologylab.oodss.distributed.client.NIOClient; +import ecologylab.oodss.distributed.common.SessionObjects; +import ecologylab.oodss.distributed.exception.MessageTooLargeException; +import ecologylab.oodss.distributed.server.DoubleThreadedNIOServer; +import ecologylab.oodss.distributed.server.clientsessionmanager.SessionHandle; +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * A request that indicates that the client wishes to be permanently disconnected from the server. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_inherit +public class DisconnectRequest extends RequestMessage +{ + public static final DisconnectRequest REUSABLE_INSTANCE = new DisconnectRequest(); + + /** + * + */ + public DisconnectRequest() + { + super(); + } + + /** + * @see ecologylab.oodss.messages.RequestMessage#performService(ecologylab.collections.Scope) + */ + @Override + public ResponseMessage performService(SCOPE localScope) + { + debug("**** running disconnect request ****"); + + SessionHandle handle = (SessionHandle) localScope.get(SessionObjects.SESSION_HANDLE); + + if (handle != null) + handle.invalidate(); + + return OkResponse.reusableInstance; + } + + public static void main(String[] args) throws BindException, UnknownHostException, IOException, + MessageTooLargeException + { + DoubleThreadedNIOServer server = DoubleThreadedNIOServer.getInstance( 10000, + InetAddress.getLocalHost(), + DefaultServicesTranslations.get(), + new Scope(), + 9999, + 99999); + + server.start(); + + System.err.println("c1 instantiate"); + NIOClient c1 = new NIOClient( "128.194.147.181", + 10000, + DefaultServicesTranslations.get(), + new Scope()); + + System.err.println("c1 connect"); + c1.connect(); + + System.err.println("c2 instantiate"); + NIOClient c2 = new NIOClient( "128.194.147.181", + 10000, + DefaultServicesTranslations.get(), + new Scope()); + + System.err.println("c2 connect"); + c2.connect(); + + System.err.println("c1 disconnect"); + c1.sendMessage(new DisconnectRequest()); + + System.err.println("c2 disconnect"); + c2.sendMessage(new DisconnectRequest()); + + System.err.println("c1 disconnect again"); + c1.sendMessage(new DisconnectRequest()); + } +} diff --git a/simplCore/src/ecologylab/oodss/messages/ErrorResponse.java b/simplCore/src/ecologylab/oodss/messages/ErrorResponse.java index dc61a85a..36eb9b2f 100644 --- a/simplCore/src/ecologylab/oodss/messages/ErrorResponse.java +++ b/simplCore/src/ecologylab/oodss/messages/ErrorResponse.java @@ -1,29 +1,29 @@ -package ecologylab.oodss.messages; - -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * Base class for all ResponseMessages that indicate errors. - * - * @author andruid - */ -@simpl_inherit -public class ErrorResponse extends ExplanationResponse -{ - public ErrorResponse() - { - super(); - } - - public ErrorResponse(String response) - { - this(); - this.explanation = response; - } - - @Override - public boolean isOK() - { - return false; - } -} +package ecologylab.oodss.messages; + +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * Base class for all ResponseMessages that indicate errors. + * + * @author andruid + */ +@simpl_inherit +public class ErrorResponse extends ExplanationResponse +{ + public ErrorResponse() + { + super(); + } + + public ErrorResponse(String response) + { + this(); + this.explanation = response; + } + + @Override + public boolean isOK() + { + return false; + } +} diff --git a/simplCore/src/ecologylab/oodss/messages/ExplanationResponse.java b/simplCore/src/ecologylab/oodss/messages/ExplanationResponse.java index 6e7ce23d..91a5caaf 100644 --- a/simplCore/src/ecologylab/oodss/messages/ExplanationResponse.java +++ b/simplCore/src/ecologylab/oodss/messages/ExplanationResponse.java @@ -1,50 +1,50 @@ -package ecologylab.oodss.messages; - -import ecologylab.collections.Scope; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Base class for all ResponseMessages that indicate errors. - * - * @author andruid, Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_inherit public class ExplanationResponse extends - ResponseMessage -{ - @simpl_scalar protected String explanation; - - public ExplanationResponse() - { - super(); - } - - public ExplanationResponse(String explanation) - { - this(); - this.explanation = explanation; - } - - @Override public boolean isOK() - { - return true; - } - - /** - * @return Returns the explanation. - */ - public String getExplanation() - { - return explanation; - } - - /** - * @param explanation - * the explanation to set - */ - public void setExplanation(String explanation) - { - this.explanation = explanation; - } - -} +package ecologylab.oodss.messages; + +import ecologylab.collections.Scope; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Base class for all ResponseMessages that indicate errors. + * + * @author andruid, Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_inherit public class ExplanationResponse extends + ResponseMessage +{ + @simpl_scalar protected String explanation; + + public ExplanationResponse() + { + super(); + } + + public ExplanationResponse(String explanation) + { + this(); + this.explanation = explanation; + } + + @Override public boolean isOK() + { + return true; + } + + /** + * @return Returns the explanation. + */ + public String getExplanation() + { + return explanation; + } + + /** + * @param explanation + * the explanation to set + */ + public void setExplanation(String explanation) + { + this.explanation = explanation; + } + +} diff --git a/simplCore/src/ecologylab/oodss/messages/HttpGetRequest.java b/simplCore/src/ecologylab/oodss/messages/HttpGetRequest.java index 6bd619ff..7e632989 100644 --- a/simplCore/src/ecologylab/oodss/messages/HttpGetRequest.java +++ b/simplCore/src/ecologylab/oodss/messages/HttpGetRequest.java @@ -1,17 +1,17 @@ -package ecologylab.oodss.messages; - -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * A message to be sent to a ServicesServer through HTTP that the Services will - * respond with an HTTP redirect URL based on whether there was an error or not. - * - * @author andrew - * @deprecated - */ - -@Deprecated -public @simpl_inherit class HttpGetRequest extends HttpRequest -{ - -} +package ecologylab.oodss.messages; + +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * A message to be sent to a ServicesServer through HTTP that the Services will + * respond with an HTTP redirect URL based on whether there was an error or not. + * + * @author andrew + * @deprecated + */ + +@Deprecated +public @simpl_inherit class HttpGetRequest extends HttpRequest +{ + +} diff --git a/simplCore/src/ecologylab/oodss/messages/HttpRequest.java b/simplCore/src/ecologylab/oodss/messages/HttpRequest.java index bb59cd4f..3c133ce7 100644 --- a/simplCore/src/ecologylab/oodss/messages/HttpRequest.java +++ b/simplCore/src/ecologylab/oodss/messages/HttpRequest.java @@ -1,66 +1,66 @@ -package ecologylab.oodss.messages; - -import ecologylab.collections.Scope; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * A message to be sent to a ServicesServer through HTTP that the Services will - * respond with an HTTP redirect URL based on whether there was an error or not. - * - * @author andrew - */ - -public @simpl_inherit class HttpRequest extends RequestMessage -{ - /** - * Redirect URL if no errors or problems occured. - */ - protected @simpl_scalar ParsedURL okResponseUrl; - - /** - * Redirect URL if an error or problem occured. - */ - protected @simpl_scalar ParsedURL errorResponseUrl; - - @Override - public ResponseMessage performService(Scope objectRegistry) - { - return OkResponse.get(); - } - - /** - * A URL can be provided, indicating the response should be accomplished with HTTP redirect. - * Used when browser security is an issue. - *

- * This is the redirect URL for response when processing is successful. - - * - * @param clientSessionScope Can be used to generate HTTP GET style arguments in the redirect URL. - * - * @return Value passed in this message. - */ - @Override - public ParsedURL okRedirectUrl(Scope clientSessionScope) - { - return okResponseUrl; - } - - /** - * A URL can be provided, indicating the response should be accomplished with HTTP redirect. - * Used when browser security is an issue. - *

- * This is the redirect URL for response when processing results in an error. - * - * @param clientSessionScope Can be used to generate HTTP GET style arguments in the redirect URL. - * - * @return Value passed in this message. - */ - @Override - public ParsedURL errorRedirectUrl(Scope clientSessionScope) - { - return errorResponseUrl; - } - -} +package ecologylab.oodss.messages; + +import ecologylab.collections.Scope; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * A message to be sent to a ServicesServer through HTTP that the Services will + * respond with an HTTP redirect URL based on whether there was an error or not. + * + * @author andrew + */ + +public @simpl_inherit class HttpRequest extends RequestMessage +{ + /** + * Redirect URL if no errors or problems occured. + */ + protected @simpl_scalar ParsedURL okResponseUrl; + + /** + * Redirect URL if an error or problem occured. + */ + protected @simpl_scalar ParsedURL errorResponseUrl; + + @Override + public ResponseMessage performService(Scope objectRegistry) + { + return OkResponse.get(); + } + + /** + * A URL can be provided, indicating the response should be accomplished with HTTP redirect. + * Used when browser security is an issue. + *

+ * This is the redirect URL for response when processing is successful. + + * + * @param clientSessionScope Can be used to generate HTTP GET style arguments in the redirect URL. + * + * @return Value passed in this message. + */ + @Override + public ParsedURL okRedirectUrl(Scope clientSessionScope) + { + return okResponseUrl; + } + + /** + * A URL can be provided, indicating the response should be accomplished with HTTP redirect. + * Used when browser security is an issue. + *

+ * This is the redirect URL for response when processing results in an error. + * + * @param clientSessionScope Can be used to generate HTTP GET style arguments in the redirect URL. + * + * @return Value passed in this message. + */ + @Override + public ParsedURL errorRedirectUrl(Scope clientSessionScope) + { + return errorResponseUrl; + } + +} diff --git a/simplCore/src/ecologylab/oodss/messages/IgnoreRequest.java b/simplCore/src/ecologylab/oodss/messages/IgnoreRequest.java index 5995a76f..9309c489 100644 --- a/simplCore/src/ecologylab/oodss/messages/IgnoreRequest.java +++ b/simplCore/src/ecologylab/oodss/messages/IgnoreRequest.java @@ -1,27 +1,27 @@ -package ecologylab.oodss.messages; - -import ecologylab.collections.Scope; -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * This is a message for the case when the server wants to ignore certain requests and send nothing to the client. - * - * @author eunyee - * - */ -@simpl_inherit -public class IgnoreRequest extends RequestMessage -{ - static final IgnoreRequest reusableInstance = new IgnoreRequest(); - - @Override - public ResponseMessage performService(Scope objectRegistry) - { - return OkResponse.get(); - } - - public static IgnoreRequest get() - { - return reusableInstance; - } +package ecologylab.oodss.messages; + +import ecologylab.collections.Scope; +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * This is a message for the case when the server wants to ignore certain requests and send nothing to the client. + * + * @author eunyee + * + */ +@simpl_inherit +public class IgnoreRequest extends RequestMessage +{ + static final IgnoreRequest reusableInstance = new IgnoreRequest(); + + @Override + public ResponseMessage performService(Scope objectRegistry) + { + return OkResponse.get(); + } + + public static IgnoreRequest get() + { + return reusableInstance; + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/oodss/messages/InitConnectionRequest.java b/simplCore/src/ecologylab/oodss/messages/InitConnectionRequest.java index 4debae3d..b1a8b056 100644 --- a/simplCore/src/ecologylab/oodss/messages/InitConnectionRequest.java +++ b/simplCore/src/ecologylab/oodss/messages/InitConnectionRequest.java @@ -1,72 +1,72 @@ -/* - * Created on Feb 28, 2007 - */ -package ecologylab.oodss.messages; - -import ecologylab.collections.Scope; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * Request to start a new connection to a server. If the message has no sessionId value, then it is - * attempting to open a completely new connection. If it has a value for sessionId, it is the - * sessionId provided by a previous connection. - * - * Sending a message with a past sessionId is no guarantee of restoring the old connection; the - * server may have disposed of it. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class InitConnectionRequest extends RequestMessage -{ - @simpl_scalar - String sessionId; - - /** - * - */ - public InitConnectionRequest() - { - } - - public InitConnectionRequest(String sessionId) - { - this.sessionId = sessionId; - } - - /** - * Returns null. Logic for handling initializing messages must be handled by a ClientSessionScope - * object. - * - * @see ecologylab.oodss.messages.RequestMessage#performService(ecologylab.collections.Scope) - */ - @Override - public ResponseMessage performService(Scope objectRegistry) - { - return null; - } - - /** - * @return the sessionId - */ - public String getSessionId() - { - return sessionId; - } - - public static void main(String[] args) - { - try - { - SimplTypesScope.serialize(SimplTypesScope.get("init_connection_request", InitConnectionRequest.class, - RequestMessage.class), System.out, StringFormat.XML); - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } -} +/* + * Created on Feb 28, 2007 + */ +package ecologylab.oodss.messages; + +import ecologylab.collections.Scope; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * Request to start a new connection to a server. If the message has no sessionId value, then it is + * attempting to open a completely new connection. If it has a value for sessionId, it is the + * sessionId provided by a previous connection. + * + * Sending a message with a past sessionId is no guarantee of restoring the old connection; the + * server may have disposed of it. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class InitConnectionRequest extends RequestMessage +{ + @simpl_scalar + String sessionId; + + /** + * + */ + public InitConnectionRequest() + { + } + + public InitConnectionRequest(String sessionId) + { + this.sessionId = sessionId; + } + + /** + * Returns null. Logic for handling initializing messages must be handled by a ClientSessionScope + * object. + * + * @see ecologylab.oodss.messages.RequestMessage#performService(ecologylab.collections.Scope) + */ + @Override + public ResponseMessage performService(Scope objectRegistry) + { + return null; + } + + /** + * @return the sessionId + */ + public String getSessionId() + { + return sessionId; + } + + public static void main(String[] args) + { + try + { + SimplTypesScope.serialize(SimplTypesScope.get("init_connection_request", InitConnectionRequest.class, + RequestMessage.class), System.out, StringFormat.XML); + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/simplCore/src/ecologylab/oodss/messages/InitConnectionResponse.java b/simplCore/src/ecologylab/oodss/messages/InitConnectionResponse.java index 6e53dac3..ca3ba770 100644 --- a/simplCore/src/ecologylab/oodss/messages/InitConnectionResponse.java +++ b/simplCore/src/ecologylab/oodss/messages/InitConnectionResponse.java @@ -1,54 +1,54 @@ -/* - * Created on Feb 28, 2007 - */ -package ecologylab.oodss.messages; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Response to a request to connect to a server. On a successful connection, sessionId will contain - * the server-assigned session identifier. If the connection failed, sessionId will be null. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public @simpl_inherit -class InitConnectionResponse extends ResponseMessage -{ - /** - * The session identifier used for all communications between this client and the server. If the - * value is null, it means the connection failed. - */ - @simpl_scalar - String sessionId; - - /** - * - */ - public InitConnectionResponse() - { - } - - public InitConnectionResponse(String sessionId) - { - this.sessionId = sessionId; - } - - /** - * @see ecologylab.oodss.messages.ResponseMessage#isOK() - */ - @Override - public boolean isOK() - { - return sessionId != null; - } - - /** - * @return the sessionId - */ - public String getSessionId() - { - return sessionId; - } - -} +/* + * Created on Feb 28, 2007 + */ +package ecologylab.oodss.messages; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Response to a request to connect to a server. On a successful connection, sessionId will contain + * the server-assigned session identifier. If the connection failed, sessionId will be null. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public @simpl_inherit +class InitConnectionResponse extends ResponseMessage +{ + /** + * The session identifier used for all communications between this client and the server. If the + * value is null, it means the connection failed. + */ + @simpl_scalar + String sessionId; + + /** + * + */ + public InitConnectionResponse() + { + } + + public InitConnectionResponse(String sessionId) + { + this.sessionId = sessionId; + } + + /** + * @see ecologylab.oodss.messages.ResponseMessage#isOK() + */ + @Override + public boolean isOK() + { + return sessionId != null; + } + + /** + * @return the sessionId + */ + public String getSessionId() + { + return sessionId; + } + +} diff --git a/simplCore/src/ecologylab/oodss/messages/MessageTypes.java b/simplCore/src/ecologylab/oodss/messages/MessageTypes.java index bb526327..8f591f2d 100644 --- a/simplCore/src/ecologylab/oodss/messages/MessageTypes.java +++ b/simplCore/src/ecologylab/oodss/messages/MessageTypes.java @@ -1,13 +1,13 @@ -package ecologylab.oodss.messages; - -/** - * Describes the types of messages that can be passed through the network via sockets. - * - * @author blake - */ -public interface MessageTypes -{ - public static final String NAVIGATE = "navigate"; - public static final String LOGIN = "login"; - public static final String LOGOUT = "logout"; -} +package ecologylab.oodss.messages; + +/** + * Describes the types of messages that can be passed through the network via sockets. + * + * @author blake + */ +public interface MessageTypes +{ + public static final String NAVIGATE = "navigate"; + public static final String LOGIN = "login"; + public static final String LOGOUT = "logout"; +} diff --git a/simplCore/src/ecologylab/oodss/messages/OkResponse.java b/simplCore/src/ecologylab/oodss/messages/OkResponse.java index ba5d30d6..0b214e8e 100644 --- a/simplCore/src/ecologylab/oodss/messages/OkResponse.java +++ b/simplCore/src/ecologylab/oodss/messages/OkResponse.java @@ -1,29 +1,29 @@ -package ecologylab.oodss.messages; - -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * Base class for all ResponseMessages that were processed successfully. - * - * @author andruid - */ -@simpl_inherit -public class OkResponse extends ResponseMessage -{ - public static final OkResponse reusableInstance = new OkResponse(); - - public OkResponse() - { - super(); - } - - @Override public boolean isOK() - { - return true; - } - - public static OkResponse get() - { - return reusableInstance; - } -} +package ecologylab.oodss.messages; + +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * Base class for all ResponseMessages that were processed successfully. + * + * @author andruid + */ +@simpl_inherit +public class OkResponse extends ResponseMessage +{ + public static final OkResponse reusableInstance = new OkResponse(); + + public OkResponse() + { + super(); + } + + @Override public boolean isOK() + { + return true; + } + + public static OkResponse get() + { + return reusableInstance; + } +} diff --git a/simplCore/src/ecologylab/oodss/messages/Ping.java b/simplCore/src/ecologylab/oodss/messages/Ping.java index 3e97d3dc..4d81cd16 100644 --- a/simplCore/src/ecologylab/oodss/messages/Ping.java +++ b/simplCore/src/ecologylab/oodss/messages/Ping.java @@ -1,18 +1,18 @@ -package ecologylab.oodss.messages; - -import ecologylab.collections.Scope; -import ecologylab.serialization.annotations.simpl_inherit; - -public @simpl_inherit class Ping extends RequestMessage -{ - /** - * @see ecologylab.oodss.messages.HttpRequest#performService(ecologylab.collections.Scope) - */ - @Override public ResponseMessage performService(Scope objectRegistry) - { - debug("ping "+System.currentTimeMillis()); - - return new Pong(); - } - -} +package ecologylab.oodss.messages; + +import ecologylab.collections.Scope; +import ecologylab.serialization.annotations.simpl_inherit; + +public @simpl_inherit class Ping extends RequestMessage +{ + /** + * @see ecologylab.oodss.messages.HttpRequest#performService(ecologylab.collections.Scope) + */ + @Override public ResponseMessage performService(Scope objectRegistry) + { + debug("ping "+System.currentTimeMillis()); + + return new Pong(); + } + +} diff --git a/simplCore/src/ecologylab/oodss/messages/PingRequest.java b/simplCore/src/ecologylab/oodss/messages/PingRequest.java index ec1287e6..be144fd0 100644 --- a/simplCore/src/ecologylab/oodss/messages/PingRequest.java +++ b/simplCore/src/ecologylab/oodss/messages/PingRequest.java @@ -1,7 +1,7 @@ -package ecologylab.oodss.messages; - -import ecologylab.serialization.annotations.simpl_inherit; - -public @simpl_inherit class PingRequest extends HttpRequest -{ -} +package ecologylab.oodss.messages; + +import ecologylab.serialization.annotations.simpl_inherit; + +public @simpl_inherit class PingRequest extends HttpRequest +{ +} diff --git a/simplCore/src/ecologylab/oodss/messages/Pong.java b/simplCore/src/ecologylab/oodss/messages/Pong.java index 5926cf96..3b4a2f69 100644 --- a/simplCore/src/ecologylab/oodss/messages/Pong.java +++ b/simplCore/src/ecologylab/oodss/messages/Pong.java @@ -1,39 +1,39 @@ -package ecologylab.oodss.messages; - -import ecologylab.collections.Scope; -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * Base class for all ResponseMessages that were processed successfully. - * - * @author andruid - */ -@simpl_inherit -public class Pong extends ResponseMessage -{ - public static final Pong reusableInstance = new Pong(); - - public Pong() - { - super(); - } - - @Override public boolean isOK() - { - return true; - } - - public static Pong get() - { - return reusableInstance; - } - - /** - * @see ecologylab.oodss.messages.ResponseMessage#processResponse(ecologylab.collections.Scope) - */ - @Override public void processResponse(Scope objectRegistry) - { - debug("pong: "+System.currentTimeMillis()); - super.processResponse(objectRegistry); - } -} +package ecologylab.oodss.messages; + +import ecologylab.collections.Scope; +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * Base class for all ResponseMessages that were processed successfully. + * + * @author andruid + */ +@simpl_inherit +public class Pong extends ResponseMessage +{ + public static final Pong reusableInstance = new Pong(); + + public Pong() + { + super(); + } + + @Override public boolean isOK() + { + return true; + } + + public static Pong get() + { + return reusableInstance; + } + + /** + * @see ecologylab.oodss.messages.ResponseMessage#processResponse(ecologylab.collections.Scope) + */ + @Override public void processResponse(Scope objectRegistry) + { + debug("pong: "+System.currentTimeMillis()); + super.processResponse(objectRegistry); + } +} diff --git a/simplCore/src/ecologylab/oodss/messages/RequestMessage.java b/simplCore/src/ecologylab/oodss/messages/RequestMessage.java index fa4b4e10..2d6ce9e0 100644 --- a/simplCore/src/ecologylab/oodss/messages/RequestMessage.java +++ b/simplCore/src/ecologylab/oodss/messages/RequestMessage.java @@ -1,79 +1,79 @@ -package ecologylab.oodss.messages; - -import ecologylab.collections.Scope; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * Abstract base class for ecologylab.oodss DCF request messages. - * - * @author blake - * @author andruid - */ -@simpl_inherit -public abstract class RequestMessage extends ServiceMessage implements - SendableRequest -{ - public RequestMessage() - { - super(); - } - - /** - * Perform the service associated with the request, using the supplied context as needed. - * - * @param localScope - * Context to perform it in/with. - * @return Response to pass back to the (remote) caller. - */ - public abstract ResponseMessage performService(S clientSessionScope); - - /** - * Indicates whether or not this type of message may be ignored by the server, if the server - * becomes backed-up. For example, a RequestMessage subclass that simply requests the server's - * current state may be ignored if a more recent copy of one has arrived later. - * - * By default, RequestMessages are not disposable; this method should be overriden if they are to - * be. - * - * @return false. - */ - @Override - public boolean isDisposable() - { - return false; - } - - /** - * A URL can be provided, indicating the response should be accomplished with HTTP redirect. Used - * when browser security is an issue. - *

- * This is the redirect URL for response when processing is successful. - * - * @param clientSessionScope - * Can be used to generate HTTP GET style arguments in the redirect URL. - * - * @return null in this the base class case. - */ - public ParsedURL okRedirectUrl(S clientSessionScope) - { - return null; - } - - /** - * A URL can be provided, indicating the response should be accomplished with HTTP redirect. Used - * when browser security is an issue. - *

- * This is the redirect URL for response when processing results in an error. - * - * @param clientSessionScope - * Can be used to generate HTTP GET style arguments in the redirect URL. - * - * @return null in this the base class case. - */ - public ParsedURL errorRedirectUrl(S clientSessionScope) - { - return null; - } - -} +package ecologylab.oodss.messages; + +import ecologylab.collections.Scope; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * Abstract base class for ecologylab.oodss DCF request messages. + * + * @author blake + * @author andruid + */ +@simpl_inherit +public abstract class RequestMessage extends ServiceMessage implements + SendableRequest +{ + public RequestMessage() + { + super(); + } + + /** + * Perform the service associated with the request, using the supplied context as needed. + * + * @param localScope + * Context to perform it in/with. + * @return Response to pass back to the (remote) caller. + */ + public abstract ResponseMessage performService(S clientSessionScope); + + /** + * Indicates whether or not this type of message may be ignored by the server, if the server + * becomes backed-up. For example, a RequestMessage subclass that simply requests the server's + * current state may be ignored if a more recent copy of one has arrived later. + * + * By default, RequestMessages are not disposable; this method should be overriden if they are to + * be. + * + * @return false. + */ + @Override + public boolean isDisposable() + { + return false; + } + + /** + * A URL can be provided, indicating the response should be accomplished with HTTP redirect. Used + * when browser security is an issue. + *

+ * This is the redirect URL for response when processing is successful. + * + * @param clientSessionScope + * Can be used to generate HTTP GET style arguments in the redirect URL. + * + * @return null in this the base class case. + */ + public ParsedURL okRedirectUrl(S clientSessionScope) + { + return null; + } + + /** + * A URL can be provided, indicating the response should be accomplished with HTTP redirect. Used + * when browser security is an issue. + *

+ * This is the redirect URL for response when processing results in an error. + * + * @param clientSessionScope + * Can be used to generate HTTP GET style arguments in the redirect URL. + * + * @return null in this the base class case. + */ + public ParsedURL errorRedirectUrl(S clientSessionScope) + { + return null; + } + +} diff --git a/simplCore/src/ecologylab/oodss/messages/ResponseMessage.java b/simplCore/src/ecologylab/oodss/messages/ResponseMessage.java index 4b256aea..9b586285 100644 --- a/simplCore/src/ecologylab/oodss/messages/ResponseMessage.java +++ b/simplCore/src/ecologylab/oodss/messages/ResponseMessage.java @@ -1,37 +1,37 @@ -package ecologylab.oodss.messages; - -import ecologylab.collections.Scope; -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * Abstract base class for ecologylab.oodss DCF response messages. - * - * @author blake - * @author andruid - */ -@simpl_inherit abstract public class ResponseMessage extends ServiceMessage -{ - public ResponseMessage() - { - } - - /** - * Let's the client easily test for OK or error. - * - * @return true if the response is not an error of some kind. - */ - public abstract boolean isOK(); - - /** - * Allows for custom processing of ResponseMessages by ServicesClient, - * without extending that. - * - * @param objectRegistry - * provide a context for response message processing. - * - */ - public void processResponse(S objectRegistry) - { - - } -} +package ecologylab.oodss.messages; + +import ecologylab.collections.Scope; +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * Abstract base class for ecologylab.oodss DCF response messages. + * + * @author blake + * @author andruid + */ +@simpl_inherit abstract public class ResponseMessage extends ServiceMessage +{ + public ResponseMessage() + { + } + + /** + * Let's the client easily test for OK or error. + * + * @return true if the response is not an error of some kind. + */ + public abstract boolean isOK(); + + /** + * Allows for custom processing of ResponseMessages by ServicesClient, + * without extending that. + * + * @param objectRegistry + * provide a context for response message processing. + * + */ + public void processResponse(S objectRegistry) + { + + } +} diff --git a/simplCore/src/ecologylab/oodss/messages/SendableRequest.java b/simplCore/src/ecologylab/oodss/messages/SendableRequest.java index cded9b0b..4e5bd4b2 100644 --- a/simplCore/src/ecologylab/oodss/messages/SendableRequest.java +++ b/simplCore/src/ecologylab/oodss/messages/SendableRequest.java @@ -1,28 +1,28 @@ -/** - * - */ -package ecologylab.oodss.messages; - - -/** - * Interface to indicate that a message can be sent over the network. Used for type checking in - * client send methods, to allow other, more specific interfaces to be used (such as - * AuthenticationRequest). - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public interface SendableRequest -{ - -// /** -// * @param requestBuffer -// */ -// StringBuilder serialize(StringBuilder requestBuffer) throws SIMPLTranslationException; - - /** - * @return - */ - boolean isDisposable(); - -} +/** + * + */ +package ecologylab.oodss.messages; + + +/** + * Interface to indicate that a message can be sent over the network. Used for type checking in + * client send methods, to allow other, more specific interfaces to be used (such as + * AuthenticationRequest). + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public interface SendableRequest +{ + +// /** +// * @param requestBuffer +// */ +// StringBuilder serialize(StringBuilder requestBuffer) throws SIMPLTranslationException; + + /** + * @return + */ + boolean isDisposable(); + +} diff --git a/simplCore/src/ecologylab/oodss/messages/ServiceMessage.java b/simplCore/src/ecologylab/oodss/messages/ServiceMessage.java index 6912d0ed..a889e207 100644 --- a/simplCore/src/ecologylab/oodss/messages/ServiceMessage.java +++ b/simplCore/src/ecologylab/oodss/messages/ServiceMessage.java @@ -1,67 +1,67 @@ -package ecologylab.oodss.messages; - -import java.net.InetAddress; - -import ecologylab.collections.Scope; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Abstract base class for ecologylab.oodss DCF request and response messages. - * - * @author blake - * @author Zachary O. Dugas Toups (zach@ecologylab.net) - */ -public class ServiceMessage extends ElementState -{ - public ServiceMessage() - { - super(); - } - - @simpl_scalar - protected long timeStamp = 0; - - /** - * Contains the IP address of the host that sent this message. sender currently must be set by a - * server that receives the message and associates it with the IP address from it's packet and/or - * channel. - */ - protected InetAddress sender = null; - - /** - * Sets timeStamp to equal the current system time in milliseconds. - * - */ - public void stampTime() - { - timeStamp = System.currentTimeMillis(); - } - - /** - * @return Returns the timeStamp in milliseconds. - */ - public long getTimeStamp() - { - return timeStamp; - } - - /** - * @return the sender's IP address - */ - public InetAddress getSender() - { - return sender; - } - - /** - * This method should be called by a server when it translates this message. - * - * @param sender - * the sender's IP address to set - */ - public void setSender(InetAddress sender) - { - this.sender = sender; - } -} +package ecologylab.oodss.messages; + +import java.net.InetAddress; + +import ecologylab.collections.Scope; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Abstract base class for ecologylab.oodss DCF request and response messages. + * + * @author blake + * @author Zachary O. Dugas Toups (zach@ecologylab.net) + */ +public class ServiceMessage extends ElementState +{ + public ServiceMessage() + { + super(); + } + + @simpl_scalar + protected long timeStamp = 0; + + /** + * Contains the IP address of the host that sent this message. sender currently must be set by a + * server that receives the message and associates it with the IP address from it's packet and/or + * channel. + */ + protected InetAddress sender = null; + + /** + * Sets timeStamp to equal the current system time in milliseconds. + * + */ + public void stampTime() + { + timeStamp = System.currentTimeMillis(); + } + + /** + * @return Returns the timeStamp in milliseconds. + */ + public long getTimeStamp() + { + return timeStamp; + } + + /** + * @return the sender's IP address + */ + public InetAddress getSender() + { + return sender; + } + + /** + * This method should be called by a server when it translates this message. + * + * @param sender + * the sender's IP address to set + */ + public void setSender(InetAddress sender) + { + this.sender = sender; + } +} diff --git a/simplCore/src/ecologylab/oodss/messages/SetPreferences.java b/simplCore/src/ecologylab/oodss/messages/SetPreferences.java index 4ad5a9cb..5639e9c7 100644 --- a/simplCore/src/ecologylab/oodss/messages/SetPreferences.java +++ b/simplCore/src/ecologylab/oodss/messages/SetPreferences.java @@ -1,98 +1,98 @@ -package ecologylab.oodss.messages; - -import ecologylab.appframework.types.prefs.PrefSet; -import ecologylab.collections.Scope; -import ecologylab.generic.ConsoleUtils; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * The message sent by ServicesClientApplet to Java application running ServicesServer at - * startup to configure preferences. - * - * @author blake - * @author andruid - */ -@simpl_inherit -@Deprecated public class SetPreferences -extends RequestMessage -{ - static boolean firstTime = true; - - @simpl_composite protected PrefSet preferencesSet; - - public SetPreferences() - { - super(); - } - - public SetPreferences(PrefSet preferencesSet) - { - super(); - this.preferencesSet = preferencesSet; - } - public SetPreferences(String preferencesSetString, SimplTypesScope translationScope) - throws SIMPLTranslationException - { - this((PrefSet) translationScope.deserialize(preferencesSetString, StringFormat.XML)); - } - - /** - * Adds the set of Prefs to the Preferences registry on the host machine. This is now generally handled automatically. - */ - @Override public ResponseMessage performService(Scope clientConnectionScope) - { - debug("performService() " + clientConnectionScope.dump()); - if (firstTime) - { - firstTime = false; - - ResponseMessage response = setupApplication(clientConnectionScope); - if (response instanceof ErrorResponse) - { - handleErrorWhileLoading(clientConnectionScope); - return response; - } - - ConsoleUtils.obtrusiveConsoleOutput("SetPreferences.sending ResponseMessage(OK)"); - } - else - { - handleAlreadyLoaded(clientConnectionScope); - } - - return OkResponse.get(); - } - - /** - * This is a hook inside the performServices method which should be overridden by any - * class that extends this object. It defines the steps necessary to setup an application - * upon receiving and processing a SetPreferences message. - * - * @param clientConnectionScope - */ - protected ResponseMessage setupApplication(Scope clientConnectionScope) { return OkResponse.get(); } - - /** - * Method for handling all SetPreferences messages after the first. Should be overridden by - * any class that extends this object to properly handle these situations on message specific basis. - * - */ - protected void handleAlreadyLoaded(Scope clientConnectionScope) - { - debug("IGNORING: preferences were previously loaded."); - } - - protected void handleErrorWhileLoading(Scope clientConnectionScope) - { - - } - - public PrefSet preferencesSet() - { - return this.preferencesSet; - } -} +package ecologylab.oodss.messages; + +import ecologylab.appframework.types.prefs.PrefSet; +import ecologylab.collections.Scope; +import ecologylab.generic.ConsoleUtils; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * The message sent by ServicesClientApplet to Java application running ServicesServer at + * startup to configure preferences. + * + * @author blake + * @author andruid + */ +@simpl_inherit +@Deprecated public class SetPreferences +extends RequestMessage +{ + static boolean firstTime = true; + + @simpl_composite protected PrefSet preferencesSet; + + public SetPreferences() + { + super(); + } + + public SetPreferences(PrefSet preferencesSet) + { + super(); + this.preferencesSet = preferencesSet; + } + public SetPreferences(String preferencesSetString, SimplTypesScope translationScope) + throws SIMPLTranslationException + { + this((PrefSet) translationScope.deserialize(preferencesSetString, StringFormat.XML)); + } + + /** + * Adds the set of Prefs to the Preferences registry on the host machine. This is now generally handled automatically. + */ + @Override public ResponseMessage performService(Scope clientConnectionScope) + { + debug("performService() " + clientConnectionScope.dump()); + if (firstTime) + { + firstTime = false; + + ResponseMessage response = setupApplication(clientConnectionScope); + if (response instanceof ErrorResponse) + { + handleErrorWhileLoading(clientConnectionScope); + return response; + } + + ConsoleUtils.obtrusiveConsoleOutput("SetPreferences.sending ResponseMessage(OK)"); + } + else + { + handleAlreadyLoaded(clientConnectionScope); + } + + return OkResponse.get(); + } + + /** + * This is a hook inside the performServices method which should be overridden by any + * class that extends this object. It defines the steps necessary to setup an application + * upon receiving and processing a SetPreferences message. + * + * @param clientConnectionScope + */ + protected ResponseMessage setupApplication(Scope clientConnectionScope) { return OkResponse.get(); } + + /** + * Method for handling all SetPreferences messages after the first. Should be overridden by + * any class that extends this object to properly handle these situations on message specific basis. + * + */ + protected void handleAlreadyLoaded(Scope clientConnectionScope) + { + debug("IGNORING: preferences were previously loaded."); + } + + protected void handleErrorWhileLoading(Scope clientConnectionScope) + { + + } + + public PrefSet preferencesSet() + { + return this.preferencesSet; + } +} diff --git a/simplCore/src/ecologylab/oodss/messages/SubmitHttpRequest.java b/simplCore/src/ecologylab/oodss/messages/SubmitHttpRequest.java index d4e86408..77b2b310 100644 --- a/simplCore/src/ecologylab/oodss/messages/SubmitHttpRequest.java +++ b/simplCore/src/ecologylab/oodss/messages/SubmitHttpRequest.java @@ -1,18 +1,18 @@ -package ecologylab.oodss.messages; - -import ecologylab.collections.Scope; -import ecologylab.serialization.annotations.simpl_composite; - -public class SubmitHttpRequest extends HttpGetRequest -{ - protected @simpl_composite SubmitMessage submitMessage; - - @Override public ResponseMessage performService(Scope objectRegistry) - { - if (submitMessage != null) - return submitMessage.performService(objectRegistry); - else - return new ErrorResponse("Failed to perform service. No SubmitMessage provided."); - } - -} +package ecologylab.oodss.messages; + +import ecologylab.collections.Scope; +import ecologylab.serialization.annotations.simpl_composite; + +public class SubmitHttpRequest extends HttpGetRequest +{ + protected @simpl_composite SubmitMessage submitMessage; + + @Override public ResponseMessage performService(Scope objectRegistry) + { + if (submitMessage != null) + return submitMessage.performService(objectRegistry); + else + return new ErrorResponse("Failed to perform service. No SubmitMessage provided."); + } + +} diff --git a/simplCore/src/ecologylab/oodss/messages/SubmitMessage.java b/simplCore/src/ecologylab/oodss/messages/SubmitMessage.java index cdd20337..418492a6 100644 --- a/simplCore/src/ecologylab/oodss/messages/SubmitMessage.java +++ b/simplCore/src/ecologylab/oodss/messages/SubmitMessage.java @@ -1,20 +1,20 @@ -package ecologylab.oodss.messages; - -import ecologylab.collections.Scope; -import ecologylab.serialization.annotations.simpl_inherit; - -@simpl_inherit -public class SubmitMessage extends RequestMessage -{ - public SubmitMessage() - { - - } - - @Override - public ResponseMessage performService(Scope objectRegistry) - { - return OkResponse.get(); - } - -} +package ecologylab.oodss.messages; + +import ecologylab.collections.Scope; +import ecologylab.serialization.annotations.simpl_inherit; + +@simpl_inherit +public class SubmitMessage extends RequestMessage +{ + public SubmitMessage() + { + + } + + @Override + public ResponseMessage performService(Scope objectRegistry) + { + return OkResponse.get(); + } + +} diff --git a/simplCore/src/ecologylab/oodss/messages/UrlMessage.java b/simplCore/src/ecologylab/oodss/messages/UrlMessage.java index cda4612a..2533f634 100644 --- a/simplCore/src/ecologylab/oodss/messages/UrlMessage.java +++ b/simplCore/src/ecologylab/oodss/messages/UrlMessage.java @@ -1,23 +1,23 @@ -package ecologylab.oodss.messages; - - -import ecologylab.collections.Scope; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -@simpl_inherit -public class UrlMessage extends RequestMessage -{ - @simpl_scalar protected String url = ""; -// @xml_attribute protected ParsedURL purl; - @simpl_scalar protected String collection = ""; - - - public @Override ResponseMessage performService(Scope objectRegistry) - { -// String datastore = HTTPPostServer.datastore + collection +"//"+(new Date()).getTime() + "//"; -// HTMLDom.downloadHTMLPage(url, collection, datastore); - return OkResponse.get(); - } - +package ecologylab.oodss.messages; + + +import ecologylab.collections.Scope; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +@simpl_inherit +public class UrlMessage extends RequestMessage +{ + @simpl_scalar protected String url = ""; +// @xml_attribute protected ParsedURL purl; + @simpl_scalar protected String collection = ""; + + + public @Override ResponseMessage performService(Scope objectRegistry) + { +// String datastore = HTTPPostServer.datastore + collection +"//"+(new Date()).getTime() + "//"; +// HTMLDom.downloadHTMLPage(url, collection, datastore); + return OkResponse.get(); + } + } \ No newline at end of file diff --git a/simplCore/src/ecologylab/oodss/messages/package.html b/simplCore/src/ecologylab/oodss/messages/package.html index 2f5d3ab9..67111228 100644 --- a/simplCore/src/ecologylab/oodss/messages/package.html +++ b/simplCore/src/ecologylab/oodss/messages/package.html @@ -1,3 +1,3 @@ - -Messages passed in the ecologylab.services Distributed Computing Framework (DCF). - + +Messages passed in the ecologylab.services Distributed Computing Framework (DCF). + diff --git a/simplCore/src/ecologylab/sensor/location/EarthData.java b/simplCore/src/ecologylab/sensor/location/EarthData.java index 55e12a69..47074df1 100644 --- a/simplCore/src/ecologylab/sensor/location/EarthData.java +++ b/simplCore/src/ecologylab/sensor/location/EarthData.java @@ -1,22 +1,22 @@ -/** - * - */ -package ecologylab.sensor.location; - -/** - * Constants about the earth size and shape, for geo location calculations. - */ -public interface EarthData -{ - /** Radius of earth, in miles. */ - public static final double RADIUS_EARTH = 3959.0; - - /** Radius of earth, in feet. */ - public static final double RADIUS_EARTH_FEET = RADIUS_EARTH * 5280.0; - - /** Radius of earth, in kilometers. */ - public static final double RADIUS_EARTH_K_METERS = 6371.0; - - /** Radius of earth, in meters. */ - public static final double RADIUS_EARTH_METERS = RADIUS_EARTH_K_METERS * 1000.0; -} +/** + * + */ +package ecologylab.sensor.location; + +/** + * Constants about the earth size and shape, for geo location calculations. + */ +public interface EarthData +{ + /** Radius of earth, in miles. */ + public static final double RADIUS_EARTH = 3959.0; + + /** Radius of earth, in feet. */ + public static final double RADIUS_EARTH_FEET = RADIUS_EARTH * 5280.0; + + /** Radius of earth, in kilometers. */ + public static final double RADIUS_EARTH_K_METERS = 6371.0; + + /** Radius of earth, in meters. */ + public static final double RADIUS_EARTH_METERS = RADIUS_EARTH_K_METERS * 1000.0; +} diff --git a/simplCore/src/ecologylab/serialization/CSharpLanguage.java b/simplCore/src/ecologylab/serialization/CSharpLanguage.java index 3a4cfec6..b0fc5a60 100644 --- a/simplCore/src/ecologylab/serialization/CSharpLanguage.java +++ b/simplCore/src/ecologylab/serialization/CSharpLanguage.java @@ -1,39 +1,39 @@ -package ecologylab.serialization; - -import java.util.Collection; - -public class CSharpLanguage implements ISimplLanguage { - - @Override - public String getLanguageIdentifier() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Collection getReservedKeywords() { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean isReservedKeyword(String keyword) { - // TODO Auto-generated method stub - return false; - } - - @Override - public String convertSimplNameToLanguageName(String simplName) - throws SIMPLTranslationException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String convertLanguageNameToSimplName(String lanugageName) - throws SIMPLTranslationException { - // TODO Auto-generated method stub - return null; - } - -} +package ecologylab.serialization; + +import java.util.Collection; + +public class CSharpLanguage implements ISimplLanguage { + + @Override + public String getLanguageIdentifier() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection getReservedKeywords() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isReservedKeyword(String keyword) { + // TODO Auto-generated method stub + return false; + } + + @Override + public String convertSimplNameToLanguageName(String simplName) + throws SIMPLTranslationException { + // TODO Auto-generated method stub + return null; + } + + @Override + public String convertLanguageNameToSimplName(String lanugageName) + throws SIMPLTranslationException { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/simplCore/src/ecologylab/serialization/CharacterConstants.java b/simplCore/src/ecologylab/serialization/CharacterConstants.java index e33d557d..22ccb43b 100644 --- a/simplCore/src/ecologylab/serialization/CharacterConstants.java +++ b/simplCore/src/ecologylab/serialization/CharacterConstants.java @@ -1,11 +1,11 @@ -package ecologylab.serialization; - -/** - * Character Constants for which extra care needs to be taken while parsing. - */ -public interface CharacterConstants -{ - static public final char TAB = 0x09; - static public final char LF = 0x0a; // also known as NEWLINE - static public final char CR = 0x0d; -} +package ecologylab.serialization; + +/** + * Character Constants for which extra care needs to be taken while parsing. + */ +public interface CharacterConstants +{ + static public final char TAB = 0x09; + static public final char LF = 0x0a; // also known as NEWLINE + static public final char CR = 0x0d; +} diff --git a/simplCore/src/ecologylab/serialization/ClassDescriptor.java b/simplCore/src/ecologylab/serialization/ClassDescriptor.java index dfa6029b..f5ce844d 100644 --- a/simplCore/src/ecologylab/serialization/ClassDescriptor.java +++ b/simplCore/src/ecologylab/serialization/ClassDescriptor.java @@ -1,1443 +1,1445 @@ -package ecologylab.serialization; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import ecologylab.generic.HashMapArrayList; -import ecologylab.generic.ReflectionTools; -import ecologylab.platformspecifics.FundamentalPlatformSpecifics; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.bibtex_key; -import ecologylab.serialization.annotations.bibtex_type; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_descriptor_classes; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_map; -import ecologylab.serialization.annotations.simpl_map_key_field; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_other_tags; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.annotations.simpl_use_equals_equals; -import ecologylab.serialization.formatenums.StringFormat; -import ecologylab.serialization.types.CollectionType; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.TypeRegistry; -import ecologylab.serialization.types.element.IMappable; - -/** - * Cached object that holds all of the structures needed to optimize - * translations to and from XML for a single subclass of ElementState. A - * rootOptimizationsMap keeps track of these, using the XML tag as the key. - *

- * This structure itself, as well as the structure within it, are created just - * in time, by lazy evaluation. - * - * @author andruid - */ -@simpl_inherit -public class ClassDescriptor extends DescriptorBase - implements IMappable, Iterable { - - public static interface FieldDescriptorsDerivedEventListener { - void fieldDescriptorsDerived(Object... eventArgs); - } - - private static final String PACKAGE_CLASS_SEP = "."; - - /** - * Class object that we are describing. - */ - @simpl_scalar - private Class describedClass; - - @simpl_scalar - private String describedClassSimpleName; - - @simpl_scalar - private String describedClassPackageName; - - @simpl_composite - private ClassDescriptor superClass; - - @simpl_collection("interface") - @simpl_other_tags("inerface") - // handle spelling error that was here - private ArrayList interfaces; - - /** - * Class object that we are describing. - */ - @simpl_scalar - private Class classDescriptorClass; - - /** - * Class object that we are describing. - */ - @simpl_scalar - private Class fieldDescriptorClass; - - /** - * This is a pseudo FieldDescriptor object, defined for the class, for cases - * in which the tag for the root element or a field is determined by class - * name, not by field name. - */ - private FieldDescriptor pseudoFieldDescriptor; - - /** - * This flag prevents loops when creating descriptors for type graphs. - */ - private boolean isGetAndOrganizeComplete; - - /** - * Map of FieldToXMLOptimizations, with field names as keys. - * - * Used to optimize translateToXML(). Also handy for providing functionality - * like associative arrays in Perl, JavaScript, PHP, ..., but with less - * overhead, because the hashtable is only maintained per class, not per - * instance. - */ - private HashMapArrayList fieldDescriptorsByFieldName = new HashMapArrayList(); - - @simpl_nowrap - @simpl_map("field_descriptor") - @simpl_map_key_field("name") - private HashMapArrayList declaredFieldDescriptorsByFieldName = new HashMapArrayList(); - - /** - * This data structure is handy for translateFromXML(). There can be - * multiple tags (keys in this map) for a single FieldDescriptor if @simpl_other_tags - * is used. - */ - private HashMap allFieldDescriptorsByTagNames = new HashMap(); - - private HashMap allFieldDescriptorsByTLVIds = new HashMap(); - - private FD fieldDescriptorForBibTeXKey = null; - - private HashMap allFieldDescriptorsByBibTeXTag = new HashMap(); - - private ArrayList attributeFieldDescriptors = new ArrayList(); - - private ArrayList elementFieldDescriptors = new ArrayList();; - - private FD scalarValueFieldDescripotor = null; - - /** - * Global map of all ClassDescriptors. Key is the full, qualified name of - * the class == describedClassName. - */ - private static final HashMap> globalClassDescriptorsMap = new HashMap>(); - - private ArrayList unresolvedScopeAnnotationFDs; - - private ArrayList unresolvedClassesAnnotationFDs; - - private String bibtexType = ""; - - @simpl_collection("generic_type_variable") - private ArrayList genericTypeVariables = new ArrayList(); - - /** - * true if the class was annotated with @simpl_use_equals_equals, and thus - * that test will be used during de/serialization to detect equivalent - * objects - */ - @simpl_scalar - private boolean strictObjectGraphRequired = false; - - public Class fdClass; - - @simpl_collection("generic_type_var") - private ArrayList genericTypeVars = null; - - private ArrayList declaredGenericTypeVarNames = null; - - @simpl_collection("super_class_generic_type_var") - private ArrayList superClassGenericTypeVars = null; - - @simpl_scalar - private String explictObjectiveCTypeName; - - private boolean isCloned; - - private ClassDescriptor clonedFrom; - - private List fieldDescriptorsDerivedEventListeners; - - static { - TypeRegistry.init(); - } - - /** - * Default constructor only for use by translateFromXML(). - */ - public ClassDescriptor() { - super(); - } - - /** - * Constructor typically used by this class for creating a ClassDescriptor - * given its Java Class. - * - * @param thatClass - */ - protected ClassDescriptor(Class thatClass) { - super(XMLTools.getXmlTagName(thatClass, SimplTypesScope.STATE), - thatClass.getName()); - - this.describedClass = thatClass; - this.describedClassSimpleName = thatClass.getSimpleName(); - this.describedClassPackageName = thatClass.getPackage().getName(); - - final simpl_descriptor_classes descriptorsClassesAnnotation = thatClass - .getAnnotation(simpl_descriptor_classes.class); - if (descriptorsClassesAnnotation != null) { - classDescriptorClass = (Class) descriptorsClassesAnnotation - .value()[0]; - fieldDescriptorClass = (Class) descriptorsClassesAnnotation - .value()[1]; - } - - if (thatClass.isAnnotationPresent(simpl_inherit.class)) - this.superClass = getClassDescriptor(thatClass.getSuperclass()); - - addGenericTypeVariables(); - if (javaParser != null) { - comment = javaParser.getJavaDocComment(thatClass); - } - if (thatClass.isAnnotationPresent(simpl_use_equals_equals.class)) { - this.strictObjectGraphRequired = true; - } - } - - /** - * Constructor used by Meta-Metadata Compiler. - * - * @param tagName - * @param comment - * @param describedClassPackageName - * @param describedClassSimpleName - * @param superClass - * @param interfaces - */ - protected ClassDescriptor(String tagName, String comment, - String describedClassPackageName, String describedClassSimpleName, - ClassDescriptor superClass, ArrayList interfaces) { - super(tagName, describedClassPackageName + PACKAGE_CLASS_SEP - + describedClassSimpleName, comment); - - this.describedClassPackageName = describedClassPackageName; - this.describedClassSimpleName = describedClassSimpleName; - this.superClass = superClass; - this.interfaces = interfaces; - } - - /** - * Handles a text node. - */ - private FieldDescriptor scalarTextFD; - - private Object SCOPE_ANNOTATION_LOCK = new Object(); - - public FieldDescriptor getScalarTextFD() { - return scalarTextFD; - } - - void setScalarTextFD(FieldDescriptor scalarTextFD) { - this.scalarTextFD = scalarTextFD; - } - - /** - * Determines if this Class Descriptor handles a text node. - * @return Returns true if this node is a text node. - */ - public boolean hasScalarFD() { - return scalarTextFD != null; - } - - /** - * Returns a list of interfaces that this class implements - * @return - */ - public ArrayList getInterfaceList() { - return interfaces; - } - - private void addGenericTypeVariables() { - TypeVariable[] typeVariables = describedClass.getTypeParameters(); - if (typeVariables != null && typeVariables.length > 0) { - for (TypeVariable typeVariable : typeVariables) { - String typeClassName = typeVariable.getName(); - genericTypeVariables.add(typeClassName); - } - } - } - - /** - * lazy-evaluation method. - * - * @return - */ - public ArrayList getGenericTypeVars() { - if (genericTypeVars == null) { - synchronized (this) { - if (genericTypeVars == null) { - genericTypeVars = new ArrayList(); - deriveGenericTypeVariables(); - } - } - } - - return genericTypeVars; - } - - /** - * lazy-evaluation method. - * - * @return - */ - public ArrayList getSuperClassGenericTypeVars() { - if (superClassGenericTypeVars == null) { - synchronized (this) { - if (superClassGenericTypeVars == null) { - // superClassGenericTypeVars = new - // ArrayList(); - deriveSuperGenericTypeVariables(); - } - } - } - - return superClassGenericTypeVars; - } - - // added a setter to enable environment specific implementation -Fei - public void setSuperClassGenericTypeVars( - ArrayList derivedSuperClassGenericTypeVars) { - synchronized (this) { - superClassGenericTypeVars = derivedSuperClassGenericTypeVars; - } - } - - // This method is modified, refer to FundamentalPlatformSpecific package - // -Fei - private void deriveSuperGenericTypeVariables() { - FundamentalPlatformSpecifics.get() - .deriveSuperClassGenericTypeVars(this); - } - - private void deriveGenericTypeVariables() { - if (describedClass != null) // for generated descriptors, describedClass - // == null - { - TypeVariable[] typeVariables = describedClass - .getTypeParameters(); - if (typeVariables != null && typeVariables.length > 0) { - for (TypeVariable typeVariable : typeVariables) { - GenericTypeVar g = GenericTypeVar.getGenericTypeVarDef( - typeVariable, this.genericTypeVars); - this.genericTypeVars.add(g); - } - } - } - } - - @Deprecated - public ArrayList getGenericTypeVariables() { - return genericTypeVariables; - } - - @Override - public String getTagName() { - return tagName; - } - - public String getBibtexType() { - if (this.bibtexType == null || this.bibtexType.equals("")) { - return tagName; - } - return bibtexType; - } - - /** - * Obtain Optimizations object in the global scope of root Optimizations. - * Uses just-in-time / lazy evaluation. The first time this is called for a - * given ElementState class, it constructs a new Optimizations saves it in - * our rootOptimizationsMap, and returns it. - *

- * Subsequent calls merely pass back the already created object from the - * rootOptimizationsMap. - * - * @param elementState - * An ElementState object that we're looking up Optimizations - * for. - * @return - */ - public static ClassDescriptor getClassDescriptor( - Object object) { - Class thatClass = object.getClass(); - - return getClassDescriptor(thatClass); - } - - static final Class[] CONSTRUCTOR_ARGS = { Class.class }; - - /** - * Obtain Optimizations object in the global scope of root Optimizations. - * Uses just-in-time / lazy evaluation. The first time this is called for a - * given ElementState class, it constructs a new Optimizations saves it in - * our rootOptimizationsMap, and returns it. - *

- * Subsequent calls merely pass back the already created object from the - * rootOptimizationsMap. - * - * @param thatClass - * @return - */ - public static ClassDescriptor getClassDescriptor( - final Class thatClass) { - String className = thatClass.getName(); - // stay out of the synchronized block most of the time - ClassDescriptor result = globalClassDescriptorsMap - .get(className); - if (result == null || !result.isGetAndOrganizeComplete) { - // but still be thread safe! - synchronized (globalClassDescriptorsMap) { - result = globalClassDescriptorsMap.get(className); - if (result == null) { - final simpl_descriptor_classes descriptorsClassesAnnotation = thatClass - .getAnnotation(simpl_descriptor_classes.class); - if (descriptorsClassesAnnotation == null) - result = new ClassDescriptor(thatClass); - else { - Class aClass = descriptorsClassesAnnotation.value()[0]; - Object[] args = new Object[1]; - args[0] = thatClass; - - result = (ClassDescriptor) ReflectionTools - .getInstance(aClass, CONSTRUCTOR_ARGS, args); - } - globalClassDescriptorsMap.put(className, result); - - ClassDescriptor superCD = result - .getSuperClass(); - if (superCD == null || superCD.isGetAndOrganizeComplete) { - // NB: this call was moved out of the constructor to - // avoid recursion problems - result.deriveAndOrganizeFieldsRecursive(thatClass); - result.isGetAndOrganizeComplete = true; - result.handleFieldDescriptorsDerivedEvent(); - } else { - final ClassDescriptor resultFinalCopy = result; - FieldDescriptorsDerivedEventListener listener = new FieldDescriptorsDerivedEventListener() { - @Override - public void fieldDescriptorsDerived( - Object... eventArgs) { - resultFinalCopy - .deriveAndOrganizeFieldsRecursive(thatClass); - resultFinalCopy.isGetAndOrganizeComplete = true; - resultFinalCopy - .handleFieldDescriptorsDerivedEvent(); - } - }; - superCD.addFieldDescriptorDerivedEventListener(listener); - } - - // result.deriveAndOrganizeFieldsRecursive(thatClass); - // result.isGetAndOrganizeComplete = true; - - } - } - } - return result; - } - - private List fieldDescriptorsDerivedEventListeners() { - if (fieldDescriptorsDerivedEventListeners == null) - this.fieldDescriptorsDerivedEventListeners = new ArrayList(); - return fieldDescriptorsDerivedEventListeners; - } - - private void addFieldDescriptorDerivedEventListener( - FieldDescriptorsDerivedEventListener listener) { - fieldDescriptorsDerivedEventListeners().add(listener); - } - - private void handleFieldDescriptorsDerivedEvent() { - if (fieldDescriptorsDerivedEventListeners != null) { - for (FieldDescriptorsDerivedEventListener listener : fieldDescriptorsDerivedEventListeners) { - listener.fieldDescriptorsDerived(); - } - fieldDescriptorsDerivedEventListeners.clear(); - } - } - - /** - * Form a pseudo-FieldDescriptor-object for a root element. We say pseudo, - * because there is no Field corresponding to this element. The - * pseudo-FieldDescriptor-object still guides the translation process. - * - * @return - */ - public FieldDescriptor pseudoFieldDescriptor() { - FieldDescriptor result = pseudoFieldDescriptor; - if (result == null) { - synchronized (this) { - result = pseudoFieldDescriptor; - if (result == null) { - result = new FieldDescriptor(this); - pseudoFieldDescriptor = result; - } - } - } - return result; - } - - public ArrayList allFieldDescriptors() { - ArrayList allFieldDescriptors = new ArrayList(); - if (attributeFieldDescriptors != null) - allFieldDescriptors.addAll(attributeFieldDescriptors); - if (elementFieldDescriptors != null) - allFieldDescriptors.addAll(elementFieldDescriptors); - return allFieldDescriptors; - } - - public ArrayList attributeFieldDescriptors() { - return attributeFieldDescriptors; - } - - public ArrayList elementFieldDescriptors() { - return elementFieldDescriptors; - } - - public FD getFieldDescriptorByTag(String tag, SimplTypesScope tScope, - Object context) { - if (unresolvedScopeAnnotationFDs != null) - resolveUnresolvedScopeAnnotationFDs(); - - if (unresolvedClassesAnnotationFDs != null) - resolveUnresolvedClassesAnnotationFDs(); - - return allFieldDescriptorsByTagNames.get(tag); - } - - public FD getFieldDescriptorByTag(String tag, SimplTypesScope tScope) { - return getFieldDescriptorByTag(tag, tScope, null); - } - - public FD getFieldDescriptorByTLVId(int tlvId) { - if (unresolvedScopeAnnotationFDs != null) - resolveUnresolvedScopeAnnotationFDs(); - - if (unresolvedClassesAnnotationFDs != null) - resolveUnresolvedClassesAnnotationFDs(); - - return allFieldDescriptorsByTLVIds.get(tlvId); - } - - public FD getFieldDescriptorForBibTeXKey() { - return fieldDescriptorForBibTeXKey; - } - - public FD getFieldDescriptorByBibTeXTag(String bibTeXTag) { - return allFieldDescriptorsByBibTeXTag.get(bibTeXTag); - } - - public FD getFieldDescriptorByFieldName(String fieldName) { - return fieldDescriptorsByFieldName.get(fieldName); - } - - @Override - public Iterator iterator() { - return fieldDescriptorsByFieldName.iterator(); - } - - /** - * Build and return an ArrayList with Field objects for all the annotated - * fields in this class. - * - * @param fieldDescriptorClass - * The Class to use for instantiating each FieldDescriptor. The - * default is FieldDescriptor, but class objects may be passed in - * that extend that class. - * - * @return HashMapArrayList of Field objects, using the XML tag name for - * each field (not its Java field name!) as the keys. Could be - * empty. Never null. - */ - - private Class fieldDescriptorAnnotationValue( - Class thatClass) { - final simpl_descriptor_classes fieldDescriptorsClassAnnotation = thatClass - .getAnnotation(simpl_descriptor_classes.class); - Class result = null; - if (fieldDescriptorsClassAnnotation != null) { - Class annotatedFieldDescriptorClass = fieldDescriptorsClassAnnotation - .value()[1]; - if (annotatedFieldDescriptorClass != null - && FieldDescriptor.class - .isAssignableFrom(annotatedFieldDescriptorClass)) - result = (Class) annotatedFieldDescriptorClass; - } - return result; - } - - /** - * Recursive method to create optimized data structures needed for - * translation to and from XML, and also for efficient reflection-based - * access to field (descriptors) at run-time, with field name as a variable. - *

- * Recurses up the chain of inherited Java classes, when @xml_inherit is - * specified. - * - * @param fdc - * @return - */ - private synchronized void deriveAndOrganizeFieldsRecursive( - Class classWithFields) { - if (classWithFields.isAnnotationPresent(simpl_inherit.class)) - - { - ClassDescriptor superClassDescriptor = (ClassDescriptor) ClassDescriptor - .getClassDescriptor(classWithFields.getSuperclass()); - - referFieldDescriptorsFrom(superClassDescriptor); - } - - if (classWithFields.isAnnotationPresent(bibtex_type.class)) { - bibtex_type bibtexTypeAnnotation = classWithFields - .getAnnotation(bibtex_type.class); - bibtexType = bibtexTypeAnnotation.value(); - } - - debug(classWithFields.toString()); - Field[] fields = classWithFields.getDeclaredFields(); - - for (int i = 0; i < fields.length; i++) { - Field thatField = fields[i]; - - // skip static fields, since we're saving instances, - // and inclusion w each instance would be redundant. - if ((thatField.getModifiers() & Modifier.STATIC) == Modifier.STATIC) { - // debug("Skipping " + thatField + " because its static!"); - continue; - } - FieldType fieldType = FieldType.UNSET_TYPE; - - if (XMLTools.isScalar(thatField)) { - fieldType = FieldType.SCALAR; - } else if (XMLTools.representAsComposite(thatField)) { - fieldType = FieldType.COMPOSITE_ELEMENT; - } else if (XMLTools.representAsCollection(thatField)) { - // WORK AROUND TO HANDLE ENUM COLLECTIONS. - // THIS WILL NOT BE A PERMANENT SOLUTION. - if (XMLTools.isEnumCollection(thatField)) { - // Enums are scalars at the moment. - fieldType = FieldType.COLLECTION_ELEMENT; - } else { - fieldType = FieldType.COLLECTION_ELEMENT; - } - } else if (XMLTools.representAsMap(thatField)) { - fieldType = FieldType.MAP_ELEMENT; - } - if (fieldType == FieldType.UNSET_TYPE) - continue; // not a simpl serialization annotated field - - FD fieldDescriptor = newFieldDescriptor(thatField, fieldType, - (Class) fieldDescriptorClass); - - if (fieldDescriptor != null) { - fieldDescriptor.genericTypeVarsContextCD = this; - } else { - int isfdl = 1+3; - isfdl ++; - } - // create indexes for serialize - if (fieldDescriptor.getType() == FieldType.SCALAR) { - Hint xmlHint = fieldDescriptor.getXmlHint(); - switch (xmlHint) { - case XML_ATTRIBUTE: - attributeFieldDescriptors.add(fieldDescriptor); - break; - case XML_TEXT: - case XML_TEXT_CDATA: - break; - case XML_LEAF: - case XML_LEAF_CDATA: - elementFieldDescriptors.add(fieldDescriptor); - break; - } - } else { - elementFieldDescriptors.add(fieldDescriptor); - } - - if (XMLTools.isCompositeAsScalarvalue(thatField)) { - scalarValueFieldDescripotor = fieldDescriptor; - } - - // generate a warning message if a mapping is being overridden - fieldDescriptorsByFieldName.put(thatField.getName(), - fieldDescriptor); - if (classWithFields == describedClass) { - declaredFieldDescriptorsByFieldName.put(thatField.getName(), - fieldDescriptor); - } - - if (fieldDescriptor.isMarshallOnly()) { - continue; // not translated from XML, so don't add those - // mappings - } - - // find the field descriptor for bibtex citation key - bibtex_key keyAnnotation = thatField - .getAnnotation(bibtex_key.class); - if (keyAnnotation != null) { - fieldDescriptorForBibTeXKey = fieldDescriptor; - } - - // create mappings for translateFromBibTeX() --> - // allFieldDescriptorsByBibTeXTag - final String bibTeXTag = fieldDescriptor.getBibtexTagName(); - allFieldDescriptorsByBibTeXTag.put(bibTeXTag, fieldDescriptor); - - // create mappings for translateFromXML() --> - // allFieldDescriptorsByTagNames - final String fieldTagName = fieldDescriptor.getTagName(); - if (fieldDescriptor.isWrapped()) { - - FD wrapper = newFieldDescriptor(fieldDescriptor, fieldTagName, - (Class) fieldDescriptorClass); - mapTagToFdForDeserialize(fieldTagName, wrapper); - mapOtherTagsToFdForDeserialize(wrapper, - fieldDescriptor.otherTags()); - } else if (!fieldDescriptor.isPolymorphic()) // tag(s) from field, - // not from class - // :-) - { - - String tag = null; - if (fieldDescriptor.isCollection()) { - - tag = fieldDescriptor.getCollectionOrMapTagName(); - - } else { - tag = fieldTagName; - } - - if(tag == null) - { - throw new RuntimeException("Tag should never be null! Fix it!"); - } - - mapTagToFdForDeserialize(tag, fieldDescriptor); - mapOtherTagsToFdForDeserialize(fieldDescriptor, - fieldDescriptor.otherTags()); - } else { - mapPolymorphicClassDescriptors(fieldDescriptor); - } - thatField.setAccessible(true); // else -- ignore non-annotated - // fields - } // end for all fields - } - - private void referFieldDescriptorsFrom( - ClassDescriptor superClassDescriptor) { - initDeclaredGenericTypeVarNames(); - - Map bookkeeper = new HashMap(); - - for (Entry fieldDescriptorEntry : superClassDescriptor - .getFieldDescriptorsByFieldName().entrySet()) { - fieldDescriptorsByFieldName.put( - fieldDescriptorEntry.getKey(), - perhapsCloneGenericField(fieldDescriptorEntry.getValue(), - bookkeeper)); - } - - for (Entry fieldDescriptorEntry : superClassDescriptor - .getDeclaredFieldDescriptorsByFieldName().entrySet()) { - declaredFieldDescriptorsByFieldName.put( - fieldDescriptorEntry.getKey(), - perhapsCloneGenericField(fieldDescriptorEntry.getValue(), - bookkeeper)); - } - - for (Entry fieldDescriptorEntry : superClassDescriptor - .getAllFieldDescriptorsByTagNames().entrySet()) { - allFieldDescriptorsByTagNames.put( - fieldDescriptorEntry.getKey(), - perhapsCloneGenericField(fieldDescriptorEntry.getValue(), - bookkeeper)); - } - - for (Entry fieldDescriptorEntry : superClassDescriptor - .getAllFieldDescriptorsByTLVIds().entrySet()) { - allFieldDescriptorsByTLVIds.put( - fieldDescriptorEntry.getKey(), - perhapsCloneGenericField(fieldDescriptorEntry.getValue(), - bookkeeper)); - } - - for (Entry fieldDescriptorEntry : superClassDescriptor - .getAllFieldDescriptorsByBibTeXTag().entrySet()) { - allFieldDescriptorsByBibTeXTag.put( - fieldDescriptorEntry.getKey(), - perhapsCloneGenericField(fieldDescriptorEntry.getValue(), - bookkeeper)); - } - - for (FD fieldDescriptor : superClassDescriptor - .attributeFieldDescriptors()) { - attributeFieldDescriptors.add(perhapsCloneGenericField( - fieldDescriptor, bookkeeper)); - } - - for (FD fieldDescriptor : superClassDescriptor - .elementFieldDescriptors()) { - elementFieldDescriptors.add(perhapsCloneGenericField( - fieldDescriptor, bookkeeper)); - } - - FieldDescriptor scalarTextFD = superClassDescriptor.getScalarTextFD(); - if (scalarTextFD != null) { // added by Zach -- doesn't seem to be - // covered otherwise - this.setScalarTextFD(perhapsCloneGenericField(scalarTextFD, - bookkeeper)); - } - - if (superClassDescriptor.getUnresolvedScopeAnnotationFDs() != null) { - for (FD fd : superClassDescriptor.getUnresolvedScopeAnnotationFDs()) { - this.registerUnresolvedScopeAnnotationFD(perhapsCloneGenericField( - fd, bookkeeper)); - } - } - - if (superClassDescriptor.getUnresolvedClassesAnnotationFDs() != null) { - for (FD fd : superClassDescriptor - .getUnresolvedClassesAnnotationFDs()) { - this.registerUnresolvedClassesAnnotationFD(perhapsCloneGenericField( - fd, bookkeeper)); - } - } - } - - private void initDeclaredGenericTypeVarNames() { - if (declaredGenericTypeVarNames == null && describedClass != null) { - ArrayList result = new ArrayList(); - TypeVariable[] typeParams = describedClass.getTypeParameters(); - if (typeParams != null && typeParams.length > 0) { - for (TypeVariable typeParam : typeParams) - result.add(typeParam.getName()); - } - if (result.size() > 0) - declaredGenericTypeVarNames = result; - } - } - - private FDT perhapsCloneGenericField(FDT fd, - Map bookkeeper) { - if (declaredGenericTypeVarNames == null || fd.field == null) { - return fd; - } - - if (bookkeeper.containsKey(fd)) { - return (FDT) bookkeeper.get(fd); - } - - FDT result = fd; - Type genericType = fd.field.getGenericType(); - if (isTypeUsingGenericNames(genericType, declaredGenericTypeVarNames)) { - result = (FDT) fd.clone(); - result.setGenericTypeVars(null); - result.genericTypeVarsContextCD = this; - } - bookkeeper.put(fd, result); - return result; - } - - private boolean isTypeUsingGenericNames(Type genericType, - ArrayList names) { - if (genericType != null) { - if (genericType instanceof TypeVariable) { - TypeVariable tv = (TypeVariable) genericType; - if (names.contains(tv.getName()) || tv.getBounds().length > 0 - && isTypeUsingGenericNames(tv.getBounds()[0], names)) { - return true; - } - } else if (genericType instanceof WildcardType) { - WildcardType wt = (WildcardType) genericType; - if (wt.getUpperBounds().length > 0 - && isTypeUsingGenericNames(wt.getUpperBounds()[0], - names)) { - return true; - } - } else if (genericType instanceof ParameterizedType) { - ParameterizedType pt = (ParameterizedType) genericType; - Type[] args = pt.getActualTypeArguments(); - for (Type arg : args) { - if (isTypeUsingGenericNames(arg, names)) { - return true; - } - } - } - } - return false; - } - - protected void mapOtherTagsToFdForDeserialize(FD fieldDescriptor, - ArrayList otherTags) { - if (otherTags != null) { - for (String otherTag : otherTags) { - mapTagToFdForDeserialize(otherTag, fieldDescriptor); - } - } - } - - /** - * @param fieldDescriptor - */ - void mapPolymorphicClassDescriptors(FD fieldDescriptor) { - Collection tagClassDescriptors = fieldDescriptor - .getPolymorphicTags(); - - if (tagClassDescriptors != null) { - for (String tagName : tagClassDescriptors) { - mapTagToFdForDeserialize(tagName, fieldDescriptor); - } - } - - mapTagToFdForDeserialize(fieldDescriptor.getTagName(), fieldDescriptor); - } - - static final Class[] FIELD_DESCRIPTOR_ARGS = { ClassDescriptor.class, - Field.class, FieldType.class }; - - /** - * @param thatField - * @param fieldDescriptorClass - * @return - */ - private FD newFieldDescriptor(Field thatField, FieldType annotationType, - Class fieldDescriptorClass) { - if (fieldDescriptorClass == null) { - return (FD) new FieldDescriptor(this, thatField, annotationType); - } - - Object args[] = new Object[3]; - args[0] = this; - args[1] = thatField; - args[2] = annotationType; - - return ReflectionTools.getInstance(fieldDescriptorClass, - FIELD_DESCRIPTOR_ARGS, args); - } - - static final Class[] WRAPPER_FIELD_DESCRIPTOR_ARGS = { - ClassDescriptor.class, FieldDescriptor.class, String.class }; - - private FD newFieldDescriptor(FD wrappedFD, String wrapperTag, - Class fieldDescriptorClass) { - if (fieldDescriptorClass == null) { - return (FD) new FieldDescriptor(this, wrappedFD, wrapperTag); - } - - Object args[] = new Object[3]; - args[0] = this; - args[1] = wrappedFD; - args[2] = wrapperTag; - - return ReflectionTools.getInstance(fieldDescriptorClass, - WRAPPER_FIELD_DESCRIPTOR_ARGS, args); - } - - /** - * Map the tag to the FieldDescriptor for use in translateFromXML() for - * elements of this class type. - * - * @param tagName - * @param fdToMap - */ - private void mapTagToFdForDeserialize(String tagName, FD fdToMap) { - - if (!fdToMap.isWrapped()) { - FD previousMapping = allFieldDescriptorsByTagNames.put(tagName, - fdToMap); - allFieldDescriptorsByTLVIds.put(tagName.hashCode(), fdToMap); - if (previousMapping != null && previousMapping != fdToMap) { - warning(" tag <" + tagName + ">:\tfield[" + fdToMap.getName() - + "] overrides field[" + previousMapping.getName() - + "]"); - } - } - } - - /** - * Add an entry to our map of Field objects, using the field's name as the - * key. Used, for example, for ignored fields. - * - * @param fieldDescriptor - */ - void addFieldDescriptorMapping(FD fieldDescriptor) { - String tagName = fieldDescriptor.getTagName(); - if (tagName != null) { - mapTagToFdForDeserialize(tagName, fieldDescriptor); - } - } - - /** - * (used by the compiler) - * - * @param fieldDescriptor - */ - protected void addFieldDescriptor(FD fieldDescriptor) { - declaredFieldDescriptorsByFieldName.put(fieldDescriptor.getName(), - fieldDescriptor); - } - - @Override - public String toString() { - return getClassSimpleName() + "[" + this.name + "]"; - } - - public Class getDescribedClass() { - return describedClass; - } - - /** - * - * @return true if this is an empty entry, for a tag that we do not parse. - * No class is associated with such an entry. - */ - public boolean isEmpty() { - return describedClass == null; - } - - public String getDescribedClassSimpleName() { - return describedClassSimpleName; - } - - public String getDescribedClassPackageName() { - return describedClassPackageName; - } - - /** - * Get the full name of the class that this describes. Use the Class to get - * this, if there is one; else use de/serialize fields that describe this. - * - * @return - */ - public String getDescribedClassName() { - return getName(); - } - - /** - * @return The full, qualified name of the class that this describes. - */ - @Override - public String getJavaTypeName() { - return getDescribedClassName(); - } - - @Override - public String getCSharpTypeName() { - return getDescribedClassName(); - } - - @Override - public String getCSharpNamespace() { - String csTypeName = this.getCSharpTypeName(); - if (csTypeName != null) { - int pos = csTypeName.lastIndexOf('.'); - return pos > 0 ? csTypeName.substring(0, pos) - : CSHARP_PRIMITIVE_NAMESPACE; - } else { - return null; - } - } - - @Override - public String getObjectiveCTypeName() { - return explictObjectiveCTypeName != null ? explictObjectiveCTypeName - : this.getDescribedClassSimpleName(); - } - - @Override - public String getDbTypeName() { - return null; - } - - public Object getInstance() throws SIMPLTranslationException { - return XMLTools.getInstance(describedClass); - } - - public int numFields() { - return allFieldDescriptorsByTagNames.size(); - } - - /** - * The tagName. - */ - @Override - public String key() { - return tagName; - } - - public HashMapArrayList getFieldDescriptorsByFieldName() { - return fieldDescriptorsByFieldName; - } - - public HashMapArrayList getDeclaredFieldDescriptorsByFieldName() { - return declaredFieldDescriptorsByFieldName; - } - - public HashMap getAllFieldDescriptorsByTagNames() { - return allFieldDescriptorsByTagNames; - } - - public HashMap getAllFieldDescriptorsByTLVIds() { - return allFieldDescriptorsByTLVIds; - } - - public HashMap getAllFieldDescriptorsByBibTeXTag() { - return allFieldDescriptorsByBibTeXTag; - } - - public ArrayList getUnresolvedScopeAnnotationFDs() { - return this.unresolvedScopeAnnotationFDs; - } - - public ArrayList getUnresolvedClassesAnnotationFDs() { - return this.unresolvedClassesAnnotationFDs; - } - - public String getSuperClassName() { - return XMLTools.getClassSimpleName(describedClass.getSuperclass()); - } - - public static void main(String[] s) { - SimplTypesScope mostBasicTranslations = SimplTypesScope.get( - "most_basic", ClassDescriptor.class, FieldDescriptor.class, - SimplTypesScope.class); - - try { - SimplTypesScope.serialize(mostBasicTranslations, System.out, - StringFormat.XML); - } catch (SIMPLTranslationException e) { - e.printStackTrace(); - } - } - - /** - * Keep track of any FieldDescriptors with unresolved @serial_scope - * declarations so we can try to resolve them later when there is use. - * - * @param fd - */ - void registerUnresolvedScopeAnnotationFD(FD fd) { - if (unresolvedScopeAnnotationFDs == null) { - synchronized (this) { - if (unresolvedScopeAnnotationFDs == null) - unresolvedScopeAnnotationFDs = new ArrayList(); - } - } - unresolvedScopeAnnotationFDs.add(fd); - } - - void registerUnresolvedClassesAnnotationFD(FD fd) { - if (unresolvedClassesAnnotationFDs == null) { - synchronized (this) { - if (unresolvedClassesAnnotationFDs == null) - unresolvedClassesAnnotationFDs = new ArrayList(); - } - } - unresolvedClassesAnnotationFDs.add(fd); - } - - /** - * Late evaluation of @serial_scope, if it failed the first time around. - */ - public void resolvePolymorphicAnnotations() { - resolveUnresolvedScopeAnnotationFDs(); - resolveUnresolvedClassesAnnotationFDs(); - } - - public void resolveUnresolvedScopeAnnotationFDs() { - if (unresolvedScopeAnnotationFDs != null) { - synchronized (SCOPE_ANNOTATION_LOCK) { - if (unresolvedScopeAnnotationFDs != null) { - for (int i = unresolvedScopeAnnotationFDs.size() - 1; i >= 0; i--) { - FieldDescriptor fd = unresolvedScopeAnnotationFDs - .remove(i); - fd.resolveUnresolvedScopeAnnotation(); - this.mapPolymorphicClassDescriptors((FD) fd); - } - unresolvedScopeAnnotationFDs = null; - } - } - } - } - - /** - * Late evaluation of @serial_scope, if it failed the first time around. - */ - public void resolveUnresolvedClassesAnnotationFDs() { - if (unresolvedClassesAnnotationFDs != null) { - for (int i = unresolvedClassesAnnotationFDs.size() - 1; i >= 0; i--) { - FieldDescriptor fd = unresolvedClassesAnnotationFDs.remove(i); - fd.resolveUnresolvedClassesAnnotation(); - this.mapPolymorphicClassDescriptors((FD) fd); - this.mapPolymorphicClassDescriptors((FD) fd); - } - } - unresolvedClassesAnnotationFDs = null; - } - - /** - * Use the @simpl_other_tags annotation to obtain an array of alternative - * (old) tags for this class. - * - * @return The array of old tags, or null, if there is no @simpl_other_tags - * annotation. - */ - @Override - public ArrayList otherTags() { - ArrayList result = this.otherTags; - if (result == null) { - result = new ArrayList(); - - Class thisClass = getDescribedClass(); - if (thisClass != null) { - final simpl_other_tags otherTagsAnnotation = thisClass - .getAnnotation(simpl_other_tags.class); - - // commented out since getAnnotation also includes inherited - // annotations - // ElementState.xml_other_tags otherTagsAnnotation = - // thisClass.getAnnotation(ElementState.xml_other_tags.class); - if (otherTagsAnnotation != null) - for (String otherTag : otherTagsAnnotation.value()) - result.add(otherTag); - } - - this.otherTags = result; - } - return result; - } - - public FD getScalarValueFieldDescripotor() { - return scalarValueFieldDescripotor; - } - - public ClassDescriptor getSuperClass() { - return superClass; - } - - /** - * method returns whether a strict object graph is required - * - * @return true if the class was annotated with @simpl_use_equals_equals, - * and thus that test will be used during de/serialization to detect - * equivalent objects - */ - public boolean getStrictObjectGraphRequired() { - return this.strictObjectGraphRequired; - } - - /** - * Find all the Collection fields in this. Assemble a Set of them, in order - * to generate import statements. - * - * @return - */ - public Set deriveCollectionDependencies() { - HashSet result = new HashSet(); - for (FieldDescriptor fd : declaredFieldDescriptorsByFieldName) { - if (fd.isCollection()) - result.add(fd.getCollectionType()); - } - return result; - } - - /** - * Find all the Composite fields in this. Assemble a Set of them, in order - * to generate import statements. - * - * @return - */ - public Set deriveCompositeDependencies() { - HashSet result = new HashSet(); - for (FieldDescriptor fd : declaredFieldDescriptorsByFieldName) { - if (fd.isNested() || (fd.isCollection())) { - ClassDescriptor elementClassDescriptor = fd - .getElementClassDescriptor(); - if (elementClassDescriptor != null - && TypeRegistry - .getScalarTypeByName(elementClassDescriptor - .getDescribedClassName()) == null) - result.add(elementClassDescriptor); - - Collection polyClassDescriptors = fd - .getPolymorphicClassDescriptors(); - if (polyClassDescriptors != null) - for (ClassDescriptor polyCd : polyClassDescriptors) - result.add(polyCd); - } - } - if (superClass != null) { - result.add(superClass); - } - return result; - } - - /** - * Find all the Scalar fields in this. Assemble a Set of them, in order to - * generate import statements. - * - * @return - */ - public Set deriveScalarDependencies() { - HashSet result = new HashSet(); - for (FieldDescriptor fd : declaredFieldDescriptorsByFieldName) { - if (fd.isScalar()) { - ScalarType scalarType = fd.getScalarType(); - if (!scalarType.isPrimitive()) { - result.add(scalarType); - ScalarType operativeScalarType = scalarType - .operativeScalarType(); - if (!scalarType.equals(operativeScalarType)) - result.add(operativeScalarType); - } - } - } - /* - * for (String genericTypeName: genericTypeVariables) { ScalarType - * scalarType = TypeRegistry.getType(genericTypeName); if (scalarType != - * null) result.add(scalarType); } - */ - return result; - } - - @Override - public void deserializationPreHook(TranslationContext translationContext) { - synchronized (globalClassDescriptorsMap) { - String name = this.getName(); - if (name != null) { - if (globalClassDescriptorsMap.containsKey(name)) - error("Already a ClassDescriptor for " + name); - else { - globalClassDescriptorsMap.put(name, this); - } - } - } - } - - /** - * @return The list of meta-information (annotations, attributes, etc.) for - * this class. - */ - public List getMetaInformation() { - if (metaInfo == null) { - metaInfo = new ArrayList(); - - // @simpl_inherit - if (superClass != null) - metaInfo.add(new MetaInformation(simpl_inherit.class)); - - // @simpl_tag - String autoTagName = XMLTools.getXmlTagName( - getDescribedClassSimpleName(), null); - if (tagName != null && !tagName.equals("") - && !tagName.equals(autoTagName)) - metaInfo.add(new MetaInformation(simpl_tag.class, false, - tagName)); - - // @simpl_other_tags - ArrayList otherTags = otherTags(); - if (otherTags != null && otherTags.size() > 0) - metaInfo.add(new MetaInformation(simpl_other_tags.class, true, - otherTags.toArray())); - } - return metaInfo; - } - - @Override - public Object clone() { - ClassDescriptor cloned = null; - try { - cloned = (ClassDescriptor) super.clone(); - cloned.isCloned = true; - cloned.clonedFrom = this; - } catch (CloneNotSupportedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return cloned; - } - - public boolean isCloned() { - return isCloned; - } - - public ClassDescriptor getClonedFrom() { - return clonedFrom; - } - - public void setDescribedClassSimpleName(String describedClassSimpleName) { - this.describedClassSimpleName = describedClassSimpleName; - this.tagName = XMLTools.getXmlTagName(describedClassSimpleName, null); - } - - public void setDescribedClassPackageName(String describedClassPackageName) { - this.describedClassPackageName = describedClassPackageName; - } - - /** - * If this class is a generic class, such as MyClass<T>. - * - * Currently this is not implemented. Please update this javadoc when you - * implement it. - * - * @return - */ - public boolean isGenericClass() { - // TODO Auto-generated method stub - // NOT YET IMPLEMENTED! - return false; - } - - public void replace(FD oldFD, FD newFD) { - // for deserialization: - if (oldFD != null) - getAllFieldDescriptorsByTagNames().remove(oldFD.getTagName()); - getAllFieldDescriptorsByTagNames().put(newFD.getTagName(), newFD); - // for serialization: - if (oldFD != null) { - replace(attributeFieldDescriptors, oldFD, newFD); - replace(elementFieldDescriptors, oldFD, newFD); - } - } - - private static void replace(List list, T oldVal, T newVal) { - if (list == null) - return; - int i = list.indexOf(oldVal); - if (i >= 0 && i < list.size()) { - list.set(i, newVal); - } - } - -} +package ecologylab.serialization; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import ecologylab.generic.HashMapArrayList; +import ecologylab.generic.ReflectionTools; +import ecologylab.platformspecifics.FundamentalPlatformSpecifics; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.bibtex_key; +import ecologylab.serialization.annotations.bibtex_type; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_descriptor_classes; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_map; +import ecologylab.serialization.annotations.simpl_map_key_field; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_other_tags; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.annotations.simpl_use_equals_equals; +import ecologylab.serialization.formatenums.StringFormat; +import ecologylab.serialization.types.CollectionType; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.TypeRegistry; +import ecologylab.serialization.types.element.IMappable; + +/** + * Cached object that holds all of the structures needed to optimize + * translations to and from XML for a single subclass of ElementState. A + * rootOptimizationsMap keeps track of these, using the XML tag as the key. + *

+ * This structure itself, as well as the structure within it, are created just + * in time, by lazy evaluation. + * + * @author andruid + */ +@simpl_inherit +public class ClassDescriptor extends DescriptorBase + implements IMappable, Iterable { + + public static interface FieldDescriptorsDerivedEventListener { + void fieldDescriptorsDerived(Object... eventArgs); + } + + private static final String PACKAGE_CLASS_SEP = "."; + + /** + * Class object that we are describing. + */ + @simpl_scalar + private Class describedClass; + + @simpl_scalar + private String describedClassSimpleName; + + @simpl_scalar + private String describedClassPackageName; + + @simpl_composite + private ClassDescriptor superClass; + + @simpl_collection("interface") + @simpl_other_tags("inerface") + // handle spelling error that was here + private ArrayList interfaces; + + /** + * Class object that we are describing. + */ + @simpl_scalar + private Class classDescriptorClass; + + /** + * Class object that we are describing. + */ + @simpl_scalar + private Class fieldDescriptorClass; + + /** + * This is a pseudo FieldDescriptor object, defined for the class, for cases + * in which the tag for the root element or a field is determined by class + * name, not by field name. + */ + private FieldDescriptor pseudoFieldDescriptor; + + /** + * This flag prevents loops when creating descriptors for type graphs. + */ + private boolean isGetAndOrganizeComplete; + + /** + * Map of FieldToXMLOptimizations, with field names as keys. + * + * Used to optimize translateToXML(). Also handy for providing functionality + * like associative arrays in Perl, JavaScript, PHP, ..., but with less + * overhead, because the hashtable is only maintained per class, not per + * instance. + */ + private HashMapArrayList fieldDescriptorsByFieldName = new HashMapArrayList(); + + @simpl_nowrap + @simpl_map("field_descriptor") + @simpl_map_key_field("name") + private HashMapArrayList declaredFieldDescriptorsByFieldName = new HashMapArrayList(); + + /** + * This data structure is handy for translateFromXML(). There can be + * multiple tags (keys in this map) for a single FieldDescriptor if @simpl_other_tags + * is used. + */ + private HashMap allFieldDescriptorsByTagNames = new HashMap(); + + private HashMap allFieldDescriptorsByTLVIds = new HashMap(); + + private FD fieldDescriptorForBibTeXKey = null; + + private HashMap allFieldDescriptorsByBibTeXTag = new HashMap(); + + private ArrayList attributeFieldDescriptors = new ArrayList(); + + private ArrayList elementFieldDescriptors = new ArrayList();; + + private FD scalarValueFieldDescripotor = null; + + /** + * Global map of all ClassDescriptors. Key is the full, qualified name of + * the class == describedClassName. + */ + private static final HashMap> globalClassDescriptorsMap = new HashMap>(); + + private ArrayList unresolvedScopeAnnotationFDs; + + private ArrayList unresolvedClassesAnnotationFDs; + + private String bibtexType = ""; + + @simpl_collection("generic_type_variable") + private ArrayList genericTypeVariables = new ArrayList(); + + /** + * true if the class was annotated with @simpl_use_equals_equals, and thus + * that test will be used during de/serialization to detect equivalent + * objects + */ + @simpl_scalar + private boolean strictObjectGraphRequired = false; + + public Class fdClass; + + @simpl_collection("generic_type_var") + private ArrayList genericTypeVars = null; + + private ArrayList declaredGenericTypeVarNames = null; + + @simpl_collection("super_class_generic_type_var") + private ArrayList superClassGenericTypeVars = null; + + @simpl_scalar + private String explictObjectiveCTypeName; + + private boolean isCloned; + + private ClassDescriptor clonedFrom; + + private List fieldDescriptorsDerivedEventListeners; + + static { + TypeRegistry.init(); + } + + /** + * Default constructor only for use by translateFromXML(). + */ + public ClassDescriptor() { + super(); + } + + /** + * Constructor typically used by this class for creating a ClassDescriptor + * given its Java Class. + * + * @param thatClass + */ + protected ClassDescriptor(Class thatClass) { + super(XMLTools.getXmlTagName(thatClass, SimplTypesScope.STATE), + thatClass.getName()); + + this.describedClass = thatClass; + this.describedClassSimpleName = thatClass.getSimpleName(); + this.describedClassPackageName = thatClass.getPackage().getName(); + + final simpl_descriptor_classes descriptorsClassesAnnotation = thatClass + .getAnnotation(simpl_descriptor_classes.class); + if (descriptorsClassesAnnotation != null) { + classDescriptorClass = (Class) descriptorsClassesAnnotation + .value()[0]; + fieldDescriptorClass = (Class) descriptorsClassesAnnotation + .value()[1]; + } + + if (thatClass.isAnnotationPresent(simpl_inherit.class)) + this.superClass = getClassDescriptor(thatClass.getSuperclass()); + + addGenericTypeVariables(); + if (javaParser != null) { + comment = javaParser.getJavaDocComment(thatClass); + } + if (thatClass.isAnnotationPresent(simpl_use_equals_equals.class)) { + this.strictObjectGraphRequired = true; + } + } + + /** + * Constructor used by Meta-Metadata Compiler. + * + * @param tagName + * @param comment + * @param describedClassPackageName + * @param describedClassSimpleName + * @param superClass + * @param interfaces + */ + protected ClassDescriptor(String tagName, String comment, + String describedClassPackageName, String describedClassSimpleName, + ClassDescriptor superClass, ArrayList interfaces) { + super(tagName, describedClassPackageName + PACKAGE_CLASS_SEP + + describedClassSimpleName, comment); + + this.describedClassPackageName = describedClassPackageName; + this.describedClassSimpleName = describedClassSimpleName; + this.superClass = superClass; + this.interfaces = interfaces; + } + + /** + * Handles a text node. + */ + private FieldDescriptor scalarTextFD; + + private Object SCOPE_ANNOTATION_LOCK = new Object(); + + public FieldDescriptor getScalarTextFD() { + return scalarTextFD; + } + + void setScalarTextFD(FieldDescriptor scalarTextFD) { + this.scalarTextFD = scalarTextFD; + } + + /** + * Determines if this Class Descriptor handles a text node. + * @return Returns true if this node is a text node. + */ + public boolean hasScalarFD() { + return scalarTextFD != null; + } + + /** + * Returns a list of interfaces that this class implements + * @return + */ + public ArrayList getInterfaceList() { + return interfaces; + } + + private void addGenericTypeVariables() { + TypeVariable[] typeVariables = describedClass.getTypeParameters(); + if (typeVariables != null && typeVariables.length > 0) { + for (TypeVariable typeVariable : typeVariables) { + String typeClassName = typeVariable.getName(); + genericTypeVariables.add(typeClassName); + } + } + } + + /** + * lazy-evaluation method. + * + * @return + */ + public ArrayList getGenericTypeVars() { + if (genericTypeVars == null) { + synchronized (this) { + if (genericTypeVars == null) { + genericTypeVars = new ArrayList(); + deriveGenericTypeVariables(); + } + } + } + + return genericTypeVars; + } + + /** + * lazy-evaluation method. + * + * @return + */ + public ArrayList getSuperClassGenericTypeVars() { + if (superClassGenericTypeVars == null) { + synchronized (this) { + if (superClassGenericTypeVars == null) { + // superClassGenericTypeVars = new + // ArrayList(); + deriveSuperGenericTypeVariables(); + } + } + } + + return superClassGenericTypeVars; + } + + // added a setter to enable environment specific implementation -Fei + public void setSuperClassGenericTypeVars( + ArrayList derivedSuperClassGenericTypeVars) { + synchronized (this) { + superClassGenericTypeVars = derivedSuperClassGenericTypeVars; + } + } + + // This method is modified, refer to FundamentalPlatformSpecific package + // -Fei + private void deriveSuperGenericTypeVariables() { + FundamentalPlatformSpecifics.get() + .deriveSuperClassGenericTypeVars(this); + } + + private void deriveGenericTypeVariables() { + if (describedClass != null) // for generated descriptors, describedClass + // == null + { + TypeVariable[] typeVariables = describedClass + .getTypeParameters(); + if (typeVariables != null && typeVariables.length > 0) { + for (TypeVariable typeVariable : typeVariables) { + GenericTypeVar g = GenericTypeVar.getGenericTypeVarDef( + typeVariable, this.genericTypeVars); + this.genericTypeVars.add(g); + } + } + } + } + + @Deprecated + public ArrayList getGenericTypeVariables() { + return genericTypeVariables; + } + + @Override + public String getTagName() { + return tagName; + } + + public String getBibtexType() { + if (this.bibtexType == null || this.bibtexType.equals("")) { + return tagName; + } + return bibtexType; + } + + /** + * Obtain Optimizations object in the global scope of root Optimizations. + * Uses just-in-time / lazy evaluation. The first time this is called for a + * given ElementState class, it constructs a new Optimizations saves it in + * our rootOptimizationsMap, and returns it. + *

+ * Subsequent calls merely pass back the already created object from the + * rootOptimizationsMap. + * + * @param elementState + * An ElementState object that we're looking up Optimizations + * for. + * @return + */ + public static ClassDescriptor getClassDescriptor( + Object object) { + Class thatClass = object.getClass(); + + return getClassDescriptor(thatClass); + } + + static final Class[] CONSTRUCTOR_ARGS = { Class.class }; + + /** + * Obtain Optimizations object in the global scope of root Optimizations. + * Uses just-in-time / lazy evaluation. The first time this is called for a + * given ElementState class, it constructs a new Optimizations saves it in + * our rootOptimizationsMap, and returns it. + *

+ * Subsequent calls merely pass back the already created object from the + * rootOptimizationsMap. + * + * @param thatClass + * @return + */ + public static ClassDescriptor getClassDescriptor( + final Class thatClass) { + String className = thatClass.getName(); + // stay out of the synchronized block most of the time + ClassDescriptor result = globalClassDescriptorsMap + .get(className); + if (result == null || !result.isGetAndOrganizeComplete) { + // but still be thread safe! + synchronized (globalClassDescriptorsMap) { + result = globalClassDescriptorsMap.get(className); + if (result == null) { + final simpl_descriptor_classes descriptorsClassesAnnotation = thatClass + .getAnnotation(simpl_descriptor_classes.class); + if (descriptorsClassesAnnotation == null) + result = new ClassDescriptor(thatClass); + else { + Class aClass = descriptorsClassesAnnotation.value()[0]; + Object[] args = new Object[1]; + args[0] = thatClass; + + result = (ClassDescriptor) ReflectionTools + .getInstance(aClass, CONSTRUCTOR_ARGS, args); + } + globalClassDescriptorsMap.put(className, result); + + ClassDescriptor superCD = result + .getSuperClass(); + if (superCD == null || superCD.isGetAndOrganizeComplete) { + // NB: this call was moved out of the constructor to + // avoid recursion problems + result.deriveAndOrganizeFieldsRecursive(thatClass); + result.isGetAndOrganizeComplete = true; + result.handleFieldDescriptorsDerivedEvent(); + } else { + final ClassDescriptor resultFinalCopy = result; + FieldDescriptorsDerivedEventListener listener = new FieldDescriptorsDerivedEventListener() { + @Override + public void fieldDescriptorsDerived( + Object... eventArgs) { + resultFinalCopy + .deriveAndOrganizeFieldsRecursive(thatClass); + resultFinalCopy.isGetAndOrganizeComplete = true; + resultFinalCopy + .handleFieldDescriptorsDerivedEvent(); + } + }; + superCD.addFieldDescriptorDerivedEventListener(listener); + } + + // result.deriveAndOrganizeFieldsRecursive(thatClass); + // result.isGetAndOrganizeComplete = true; + + } + } + } + return result; + } + + private List fieldDescriptorsDerivedEventListeners() { + if (fieldDescriptorsDerivedEventListeners == null) + this.fieldDescriptorsDerivedEventListeners = new ArrayList(); + return fieldDescriptorsDerivedEventListeners; + } + + private void addFieldDescriptorDerivedEventListener( + FieldDescriptorsDerivedEventListener listener) { + fieldDescriptorsDerivedEventListeners().add(listener); + } + + private void handleFieldDescriptorsDerivedEvent() { + if (fieldDescriptorsDerivedEventListeners != null) { + for (FieldDescriptorsDerivedEventListener listener : fieldDescriptorsDerivedEventListeners) { + listener.fieldDescriptorsDerived(); + } + fieldDescriptorsDerivedEventListeners.clear(); + } + } + + /** + * Form a pseudo-FieldDescriptor-object for a root element. We say pseudo, + * because there is no Field corresponding to this element. The + * pseudo-FieldDescriptor-object still guides the translation process. + * + * @return + */ + public FieldDescriptor pseudoFieldDescriptor() { + FieldDescriptor result = pseudoFieldDescriptor; + if (result == null) { + synchronized (this) { + result = pseudoFieldDescriptor; + if (result == null) { + result = new FieldDescriptor(this); + pseudoFieldDescriptor = result; + } + } + } + return result; + } + + public ArrayList allFieldDescriptors() { + ArrayList allFieldDescriptors = new ArrayList(); + if (attributeFieldDescriptors != null) + allFieldDescriptors.addAll(attributeFieldDescriptors); + if (elementFieldDescriptors != null) + allFieldDescriptors.addAll(elementFieldDescriptors); + return allFieldDescriptors; + } + + public ArrayList attributeFieldDescriptors() { + return attributeFieldDescriptors; + } + + public ArrayList elementFieldDescriptors() { + return elementFieldDescriptors; + } + + public FD getFieldDescriptorByTag(String tag, SimplTypesScope tScope, + Object context) { + if (unresolvedScopeAnnotationFDs != null) + resolveUnresolvedScopeAnnotationFDs(); + + if (unresolvedClassesAnnotationFDs != null) + resolveUnresolvedClassesAnnotationFDs(); + + return allFieldDescriptorsByTagNames.get(tag); + } + + public FD getFieldDescriptorByTag(String tag, SimplTypesScope tScope) { + return getFieldDescriptorByTag(tag, tScope, null); + } + + public FD getFieldDescriptorByTLVId(int tlvId) { + if (unresolvedScopeAnnotationFDs != null) + resolveUnresolvedScopeAnnotationFDs(); + + if (unresolvedClassesAnnotationFDs != null) + resolveUnresolvedClassesAnnotationFDs(); + + return allFieldDescriptorsByTLVIds.get(tlvId); + } + + public FD getFieldDescriptorForBibTeXKey() { + return fieldDescriptorForBibTeXKey; + } + + public FD getFieldDescriptorByBibTeXTag(String bibTeXTag) { + return allFieldDescriptorsByBibTeXTag.get(bibTeXTag); + } + + public FD getFieldDescriptorByFieldName(String fieldName) { + return fieldDescriptorsByFieldName.get(fieldName); + } + + @Override + public Iterator iterator() { + return fieldDescriptorsByFieldName.iterator(); + } + + /** + * Build and return an ArrayList with Field objects for all the annotated + * fields in this class. + * + * @param fieldDescriptorClass + * The Class to use for instantiating each FieldDescriptor. The + * default is FieldDescriptor, but class objects may be passed in + * that extend that class. + * + * @return HashMapArrayList of Field objects, using the XML tag name for + * each field (not its Java field name!) as the keys. Could be + * empty. Never null. + */ + + private Class fieldDescriptorAnnotationValue( + Class thatClass) { + final simpl_descriptor_classes fieldDescriptorsClassAnnotation = thatClass + .getAnnotation(simpl_descriptor_classes.class); + Class result = null; + if (fieldDescriptorsClassAnnotation != null) { + Class annotatedFieldDescriptorClass = fieldDescriptorsClassAnnotation + .value()[1]; + if (annotatedFieldDescriptorClass != null + && FieldDescriptor.class + .isAssignableFrom(annotatedFieldDescriptorClass)) + result = (Class) annotatedFieldDescriptorClass; + } + return result; + } + + /** + * Recursive method to create optimized data structures needed for + * translation to and from XML, and also for efficient reflection-based + * access to field (descriptors) at run-time, with field name as a variable. + *

+ * Recurses up the chain of inherited Java classes, when @xml_inherit is + * specified. + * + * @param fdc + * @return + */ + private synchronized void deriveAndOrganizeFieldsRecursive( + Class classWithFields) { + if (classWithFields.isAnnotationPresent(simpl_inherit.class)) + + { + ClassDescriptor superClassDescriptor = (ClassDescriptor) ClassDescriptor + .getClassDescriptor(classWithFields.getSuperclass()); + + referFieldDescriptorsFrom(superClassDescriptor); + } + + if (classWithFields.isAnnotationPresent(bibtex_type.class)) { + bibtex_type bibtexTypeAnnotation = classWithFields + .getAnnotation(bibtex_type.class); + bibtexType = bibtexTypeAnnotation.value(); + } + + debug(classWithFields.toString()); + Field[] fields = classWithFields.getDeclaredFields(); + + for (int i = 0; i < fields.length; i++) { + Field thatField = fields[i]; + + // skip static fields, since we're saving instances, + // and inclusion w each instance would be redundant. + if ((thatField.getModifiers() & Modifier.STATIC) == Modifier.STATIC) { + // debug("Skipping " + thatField + " because its static!"); + continue; + } + FieldType fieldType = FieldType.UNSET_TYPE; + + if (XMLTools.isScalar(thatField)) { + fieldType = FieldType.SCALAR; + } else if (XMLTools.representAsComposite(thatField)) { + fieldType = FieldType.COMPOSITE_ELEMENT; + } else if (XMLTools.representAsCollection(thatField)) { + // WORK AROUND TO HANDLE ENUM COLLECTIONS. + // THIS WILL NOT BE A PERMANENT SOLUTION. + if (XMLTools.isEnumCollection(thatField)) { + // Enums are scalars at the moment. + fieldType = FieldType.COLLECTION_ELEMENT; + } else { + fieldType = FieldType.COLLECTION_ELEMENT; + } + } else if (XMLTools.representAsMap(thatField)) { + fieldType = FieldType.MAP_ELEMENT; + } + if (fieldType == FieldType.UNSET_TYPE) + continue; // not a simpl serialization annotated field + + FD fieldDescriptor = newFieldDescriptor(thatField, fieldType, + (Class) fieldDescriptorClass); + + if (fieldDescriptor != null) { + fieldDescriptor.genericTypeVarsContextCD = this; + } else { + int isfdl = 1+3; + isfdl ++; + } + // create indexes for serialize + if (fieldDescriptor.getType() == FieldType.SCALAR) { + Hint xmlHint = fieldDescriptor.getXmlHint(); + switch (xmlHint) { + case XML_ATTRIBUTE: + attributeFieldDescriptors.add(fieldDescriptor); + break; + case XML_TEXT: + case XML_TEXT_CDATA: + break; + case XML_LEAF: + case XML_LEAF_CDATA: + elementFieldDescriptors.add(fieldDescriptor); + break; + } + } else { + elementFieldDescriptors.add(fieldDescriptor); + } + + if (XMLTools.isCompositeAsScalarvalue(thatField)) { + scalarValueFieldDescripotor = fieldDescriptor; + } + + // generate a warning message if a mapping is being overridden + fieldDescriptorsByFieldName.put(thatField.getName(), + fieldDescriptor); + if (classWithFields == describedClass) { + declaredFieldDescriptorsByFieldName.put(thatField.getName(), + fieldDescriptor); + } + + if (fieldDescriptor.isMarshallOnly()) { + continue; // not translated from XML, so don't add those + // mappings + } + + // find the field descriptor for bibtex citation key + bibtex_key keyAnnotation = thatField + .getAnnotation(bibtex_key.class); + if (keyAnnotation != null) { + fieldDescriptorForBibTeXKey = fieldDescriptor; + } + + // create mappings for translateFromBibTeX() --> + // allFieldDescriptorsByBibTeXTag + final String bibTeXTag = fieldDescriptor.getBibtexTagName(); + allFieldDescriptorsByBibTeXTag.put(bibTeXTag, fieldDescriptor); + + // create mappings for translateFromXML() --> + // allFieldDescriptorsByTagNames + final String fieldTagName = fieldDescriptor.getTagName(); + if (fieldDescriptor.isWrapped()) { + + FD wrapper = newFieldDescriptor(fieldDescriptor, fieldTagName, + (Class) fieldDescriptorClass); + mapTagToFdForDeserialize(fieldTagName, wrapper); + mapOtherTagsToFdForDeserialize(wrapper, + fieldDescriptor.otherTags()); + } else if (!fieldDescriptor.isPolymorphic()) // tag(s) from field, + // not from class + // :-) + { + + String tag = null; + if (fieldDescriptor.isCollection()) { + + tag = fieldDescriptor.getCollectionOrMapTagName(); + + } else { + tag = fieldTagName; + } + + if(tag == null) + { + throw new RuntimeException("Tag should never be null! Fix it!"); + } + + mapTagToFdForDeserialize(tag, fieldDescriptor); + mapOtherTagsToFdForDeserialize(fieldDescriptor, + fieldDescriptor.otherTags()); + } else { + mapPolymorphicClassDescriptors(fieldDescriptor); + } + thatField.setAccessible(true); // else -- ignore non-annotated + // fields + } // end for all fields + } + + private void referFieldDescriptorsFrom( + ClassDescriptor superClassDescriptor) { + initDeclaredGenericTypeVarNames(); + + Map bookkeeper = new HashMap(); + + for (Entry fieldDescriptorEntry : superClassDescriptor + .getFieldDescriptorsByFieldName().entrySet()) { + fieldDescriptorsByFieldName.put( + fieldDescriptorEntry.getKey(), + perhapsCloneGenericField(fieldDescriptorEntry.getValue(), + bookkeeper)); + } + + for (Entry fieldDescriptorEntry : superClassDescriptor + .getDeclaredFieldDescriptorsByFieldName().entrySet()) { + declaredFieldDescriptorsByFieldName.put( + fieldDescriptorEntry.getKey(), + perhapsCloneGenericField(fieldDescriptorEntry.getValue(), + bookkeeper)); + } + + for (Entry fieldDescriptorEntry : superClassDescriptor + .getAllFieldDescriptorsByTagNames().entrySet()) { + allFieldDescriptorsByTagNames.put( + fieldDescriptorEntry.getKey(), + perhapsCloneGenericField(fieldDescriptorEntry.getValue(), + bookkeeper)); + } + + for (Entry fieldDescriptorEntry : superClassDescriptor + .getAllFieldDescriptorsByTLVIds().entrySet()) { + allFieldDescriptorsByTLVIds.put( + fieldDescriptorEntry.getKey(), + perhapsCloneGenericField(fieldDescriptorEntry.getValue(), + bookkeeper)); + } + + for (Entry fieldDescriptorEntry : superClassDescriptor + .getAllFieldDescriptorsByBibTeXTag().entrySet()) { + allFieldDescriptorsByBibTeXTag.put( + fieldDescriptorEntry.getKey(), + perhapsCloneGenericField(fieldDescriptorEntry.getValue(), + bookkeeper)); + } + + for (FD fieldDescriptor : superClassDescriptor + .attributeFieldDescriptors()) { + attributeFieldDescriptors.add(perhapsCloneGenericField( + fieldDescriptor, bookkeeper)); + } + + for (FD fieldDescriptor : superClassDescriptor + .elementFieldDescriptors()) { + elementFieldDescriptors.add(perhapsCloneGenericField( + fieldDescriptor, bookkeeper)); + } + + FieldDescriptor scalarTextFD = superClassDescriptor.getScalarTextFD(); + if (scalarTextFD != null) { // added by Zach -- doesn't seem to be + // covered otherwise + this.setScalarTextFD(perhapsCloneGenericField(scalarTextFD, + bookkeeper)); + } + + if (superClassDescriptor.getUnresolvedScopeAnnotationFDs() != null) { + for (FD fd : superClassDescriptor.getUnresolvedScopeAnnotationFDs()) { + this.registerUnresolvedScopeAnnotationFD(perhapsCloneGenericField( + fd, bookkeeper)); + } + } + + if (superClassDescriptor.getUnresolvedClassesAnnotationFDs() != null) { + for (FD fd : superClassDescriptor + .getUnresolvedClassesAnnotationFDs()) { + this.registerUnresolvedClassesAnnotationFD(perhapsCloneGenericField( + fd, bookkeeper)); + } + } + } + + private void initDeclaredGenericTypeVarNames() { + if (declaredGenericTypeVarNames == null && describedClass != null) { + ArrayList result = new ArrayList(); + TypeVariable[] typeParams = describedClass.getTypeParameters(); + if (typeParams != null && typeParams.length > 0) { + for (TypeVariable typeParam : typeParams) + result.add(typeParam.getName()); + } + if (result.size() > 0) + declaredGenericTypeVarNames = result; + } + } + + private FDT perhapsCloneGenericField(FDT fd, + Map bookkeeper) { + if (declaredGenericTypeVarNames == null || fd.field == null) { + return fd; + } + + if (bookkeeper.containsKey(fd)) { + return (FDT) bookkeeper.get(fd); + } + + FDT result = fd; + Type genericType = fd.field.getGenericType(); + if (isTypeUsingGenericNames(genericType, declaredGenericTypeVarNames)) { + result = (FDT) fd.clone(); + result.setGenericTypeVars(null); + result.genericTypeVarsContextCD = this; + } + bookkeeper.put(fd, result); + return result; + } + + private boolean isTypeUsingGenericNames(Type genericType, + ArrayList names) { + if (genericType != null) { + if (genericType instanceof TypeVariable) { + TypeVariable tv = (TypeVariable) genericType; + if (names.contains(tv.getName()) || tv.getBounds().length > 0 + && isTypeUsingGenericNames(tv.getBounds()[0], names)) { + return true; + } + } else if (genericType instanceof WildcardType) { + WildcardType wt = (WildcardType) genericType; + if (wt.getUpperBounds().length > 0 + && isTypeUsingGenericNames(wt.getUpperBounds()[0], + names)) { + return true; + } + } else if (genericType instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) genericType; + Type[] args = pt.getActualTypeArguments(); + for (Type arg : args) { + if (isTypeUsingGenericNames(arg, names)) { + return true; + } + } + } + } + return false; + } + + protected void mapOtherTagsToFdForDeserialize(FD fieldDescriptor, + ArrayList otherTags) { + if (otherTags != null) { + for (String otherTag : otherTags) { + mapTagToFdForDeserialize(otherTag, fieldDescriptor); + } + } + } + + /** + * @param fieldDescriptor + */ + void mapPolymorphicClassDescriptors(FD fieldDescriptor) { + Collection tagClassDescriptors = fieldDescriptor + .getPolymorphicTags(); + + if (tagClassDescriptors != null) { + for (String tagName : tagClassDescriptors) { + mapTagToFdForDeserialize(tagName, fieldDescriptor); + } + } + + mapTagToFdForDeserialize(fieldDescriptor.getTagName(), fieldDescriptor); + } + + static final Class[] FIELD_DESCRIPTOR_ARGS = { ClassDescriptor.class, + Field.class, FieldType.class }; + + /** + * @param thatField + * @param fieldDescriptorClass + * @return + */ + private FD newFieldDescriptor(Field thatField, FieldType annotationType, + Class fieldDescriptorClass) { + if (fieldDescriptorClass == null) { + return (FD) new FieldDescriptor(this, thatField, annotationType); + } + + Object args[] = new Object[3]; + args[0] = this; + args[1] = thatField; + args[2] = annotationType; + + return ReflectionTools.getInstance(fieldDescriptorClass, + FIELD_DESCRIPTOR_ARGS, args); + } + + static final Class[] WRAPPER_FIELD_DESCRIPTOR_ARGS = { + ClassDescriptor.class, FieldDescriptor.class, String.class }; + + private FD newFieldDescriptor(FD wrappedFD, String wrapperTag, + Class fieldDescriptorClass) { + if (fieldDescriptorClass == null) { + return (FD) new FieldDescriptor(this, wrappedFD, wrapperTag); + } + + Object args[] = new Object[3]; + args[0] = this; + args[1] = wrappedFD; + args[2] = wrapperTag; + + return ReflectionTools.getInstance(fieldDescriptorClass, + WRAPPER_FIELD_DESCRIPTOR_ARGS, args); + } + + /** + * Map the tag to the FieldDescriptor for use in translateFromXML() for + * elements of this class type. + * + * @param tagName + * @param fdToMap + */ + private void mapTagToFdForDeserialize(String tagName, FD fdToMap) { + + if (!fdToMap.isWrapped()) { + FD previousMapping = allFieldDescriptorsByTagNames.put(tagName, + fdToMap); + allFieldDescriptorsByTLVIds.put(tagName.hashCode(), fdToMap); + if (previousMapping != null && previousMapping != fdToMap) { + warning(" tag <" + tagName + ">:\tfield[" + fdToMap.getName() + + "] overrides field[" + previousMapping.getName() + + "]"); + } + } + } + + /** + * Add an entry to our map of Field objects, using the field's name as the + * key. Used, for example, for ignored fields. + * + * @param fieldDescriptor + */ + void addFieldDescriptorMapping(FD fieldDescriptor) { + String tagName = fieldDescriptor.getTagName(); + if (tagName != null) { + mapTagToFdForDeserialize(tagName, fieldDescriptor); + } + } + + /** + * (used by the compiler) + * + * @param fieldDescriptor + */ + protected void addFieldDescriptor(FD fieldDescriptor) { + declaredFieldDescriptorsByFieldName.put(fieldDescriptor.getName(), + fieldDescriptor); + } + + @Override + public String toString() { + return getClassSimpleName() + "[" + this.name + "]"; + } + + public Class getDescribedClass() { + return describedClass; + } + + /** + * + * @return true if this is an empty entry, for a tag that we do not parse. + * No class is associated with such an entry. + */ + public boolean isEmpty() { + return describedClass == null; + } + + public String getDescribedClassSimpleName() { + return describedClassSimpleName; + } + + public String getDescribedClassPackageName() { + return describedClassPackageName; + } + + /** + * Get the full name of the class that this describes. Use the Class to get + * this, if there is one; else use de/serialize fields that describe this. + * + * @return + */ + public String getDescribedClassName() { + return getName(); + } + + /** + * @return The full, qualified name of the class that this describes. + */ + @Override + public String getJavaTypeName() { + return getDescribedClassName(); + } + + @Override + public String getCSharpTypeName() { + return getDescribedClassName(); + } + + @Override + public String getCSharpNamespace() { + String csTypeName = this.getCSharpTypeName(); + if (csTypeName != null) { + int pos = csTypeName.lastIndexOf('.'); + return pos > 0 ? csTypeName.substring(0, pos) + : CSHARP_PRIMITIVE_NAMESPACE; + } else { + return null; + } + } + + @Override + public String getObjectiveCTypeName() { + return explictObjectiveCTypeName != null ? explictObjectiveCTypeName + : this.getDescribedClassSimpleName(); + } + + @Override + public String getDbTypeName() { + return null; + } + + public Object getInstance() throws SIMPLTranslationException { + return XMLTools.getInstance(describedClass); + } + + public int numFields() { + return allFieldDescriptorsByTagNames.size(); + } + + /** + * The tagName. + */ + @Override + public String key() { + return tagName; + } + + public HashMapArrayList getFieldDescriptorsByFieldName() { + return fieldDescriptorsByFieldName; + } + + public HashMapArrayList getDeclaredFieldDescriptorsByFieldName() { + return declaredFieldDescriptorsByFieldName; + } + + public HashMap getAllFieldDescriptorsByTagNames() { + return allFieldDescriptorsByTagNames; + } + + public HashMap getAllFieldDescriptorsByTLVIds() { + return allFieldDescriptorsByTLVIds; + } + + public HashMap getAllFieldDescriptorsByBibTeXTag() { + return allFieldDescriptorsByBibTeXTag; + } + + public ArrayList getUnresolvedScopeAnnotationFDs() { + return this.unresolvedScopeAnnotationFDs; + } + + public ArrayList getUnresolvedClassesAnnotationFDs() { + return this.unresolvedClassesAnnotationFDs; + } + + public String getSuperClassName() { + return XMLTools.getClassSimpleName(describedClass.getSuperclass()); + } + + public static void main(String[] s) { + SimplTypesScope mostBasicTranslations = SimplTypesScope.get( + "most_basic", ClassDescriptor.class, FieldDescriptor.class, + SimplTypesScope.class); + + try { + SimplTypesScope.serialize(mostBasicTranslations, System.out, + StringFormat.XML); + } catch (SIMPLTranslationException e) { + e.printStackTrace(); + } + } + + /** + * Keep track of any FieldDescriptors with unresolved @serial_scope + * declarations so we can try to resolve them later when there is use. + * + * @param fd + */ + void registerUnresolvedScopeAnnotationFD(FD fd) { + if (unresolvedScopeAnnotationFDs == null) { + synchronized (this) { + if (unresolvedScopeAnnotationFDs == null) + unresolvedScopeAnnotationFDs = new ArrayList(); + } + } + unresolvedScopeAnnotationFDs.add(fd); + } + + void registerUnresolvedClassesAnnotationFD(FD fd) { + if (unresolvedClassesAnnotationFDs == null) { + synchronized (this) { + if (unresolvedClassesAnnotationFDs == null) + unresolvedClassesAnnotationFDs = new ArrayList(); + } + } + unresolvedClassesAnnotationFDs.add(fd); + } + + /** + * Late evaluation of @serial_scope, if it failed the first time around. + */ + public void resolvePolymorphicAnnotations() { + resolveUnresolvedScopeAnnotationFDs(); + resolveUnresolvedClassesAnnotationFDs(); + } + + public void resolveUnresolvedScopeAnnotationFDs() { + if (unresolvedScopeAnnotationFDs != null) { + synchronized (SCOPE_ANNOTATION_LOCK) { + if (unresolvedScopeAnnotationFDs != null) { + for (int i = unresolvedScopeAnnotationFDs.size() - 1; i >= 0; i--) { + FieldDescriptor fd = unresolvedScopeAnnotationFDs + .remove(i); + fd.resolveUnresolvedScopeAnnotation(); + this.mapPolymorphicClassDescriptors((FD) fd); + } + unresolvedScopeAnnotationFDs = null; + } + } + } + } + + /** + * Late evaluation of @serial_scope, if it failed the first time around. + */ + public void resolveUnresolvedClassesAnnotationFDs() { + if (unresolvedClassesAnnotationFDs != null) { + for (int i = unresolvedClassesAnnotationFDs.size() - 1; i >= 0; i--) { + FieldDescriptor fd = unresolvedClassesAnnotationFDs.remove(i); + fd.resolveUnresolvedClassesAnnotation(); + this.mapPolymorphicClassDescriptors((FD) fd); + this.mapPolymorphicClassDescriptors((FD) fd); + } + } + unresolvedClassesAnnotationFDs = null; + } + + /** + * Use the @simpl_other_tags annotation to obtain an array of alternative + * (old) tags for this class. + * + * @return The array of old tags, or null, if there is no @simpl_other_tags + * annotation. + */ + @Override + public ArrayList otherTags() { + ArrayList result = this.otherTags; + if (result == null) { + result = new ArrayList(); + + Class thisClass = getDescribedClass(); + if (thisClass != null) { + final simpl_other_tags otherTagsAnnotation = thisClass + .getAnnotation(simpl_other_tags.class); + + // commented out since getAnnotation also includes inherited + // annotations + // ElementState.xml_other_tags otherTagsAnnotation = + // thisClass.getAnnotation(ElementState.xml_other_tags.class); + if (otherTagsAnnotation != null) + for (String otherTag : otherTagsAnnotation.value()) + result.add(otherTag); + } + + this.otherTags = result; + } + return result; + } + + public FD getScalarValueFieldDescripotor() { + return scalarValueFieldDescripotor; + } + + public ClassDescriptor getSuperClass() { + return superClass; + } + + /** + * method returns whether a strict object graph is required + * + * @return true if the class was annotated with @simpl_use_equals_equals, + * and thus that test will be used during de/serialization to detect + * equivalent objects + */ + public boolean getStrictObjectGraphRequired() { + return this.strictObjectGraphRequired; + } + + /** + * Find all the Collection fields in this. Assemble a Set of them, in order + * to generate import statements. + * + * @return + */ + public Set deriveCollectionDependencies() { + HashSet result = new HashSet(); + for (FieldDescriptor fd : declaredFieldDescriptorsByFieldName) { + if (fd.isCollection()) + result.add(fd.getCollectionType()); + } + return result; + } + + /** + * Find all the Composite fields in this. Assemble a Set of them, in order + * to generate import statements. + * + * @return + */ + public Set deriveCompositeDependencies() { + HashSet result = new HashSet(); + for (FieldDescriptor fd : declaredFieldDescriptorsByFieldName) { + if (fd.isNested() || (fd.isCollection())) { + ClassDescriptor elementClassDescriptor = fd + .getElementClassDescriptor(); + if (elementClassDescriptor != null + && TypeRegistry + .getScalarTypeByName(elementClassDescriptor + .getDescribedClassName()) == null) + result.add(elementClassDescriptor); + + Collection polyClassDescriptors = fd + .getPolymorphicClassDescriptors(); + if (polyClassDescriptors != null) + for (ClassDescriptor polyCd : polyClassDescriptors) + result.add(polyCd); + } + } + if (superClass != null) { + result.add(superClass); + } + return result; + } + + /** + * Find all the Scalar fields in this. Assemble a Set of them, in order to + * generate import statements. + * + * @return + */ + public Set deriveScalarDependencies() { + HashSet result = new HashSet(); + for (FieldDescriptor fd : declaredFieldDescriptorsByFieldName) { + if (fd.isScalar()) { + ScalarType scalarType = fd.getScalarType(); + if (!scalarType.isPrimitive()) { + result.add(scalarType); + ScalarType operativeScalarType = scalarType + .operativeScalarType(); + if (!scalarType.equals(operativeScalarType)) + result.add(operativeScalarType); + } + } + } + /* + * for (String genericTypeName: genericTypeVariables) { ScalarType + * scalarType = TypeRegistry.getType(genericTypeName); if (scalarType != + * null) result.add(scalarType); } + */ + return result; + } + + @Override + public void deserializationPreHook(TranslationContext translationContext) { + synchronized (globalClassDescriptorsMap) { + String name = this.getName(); + if (name != null) { + if (globalClassDescriptorsMap.containsKey(name)) + error("Already a ClassDescriptor for " + name); + else { + globalClassDescriptorsMap.put(name, this); + } + } + } + } + + /** + * @return The list of meta-information (annotations, attributes, etc.) for + * this class. + */ + public List getMetaInformation() { + if (metaInfo == null) { + metaInfo = new ArrayList(); + + // @simpl_inherit + if (superClass != null) + metaInfo.add(new MetaInformation(simpl_inherit.class)); + + // @simpl_tag + String autoTagName = XMLTools.getXmlTagName( + getDescribedClassSimpleName(), null); + if (tagName != null && !tagName.equals("") + && !tagName.equals(autoTagName)) + metaInfo.add(new MetaInformation(simpl_tag.class, false, + tagName)); + + // @simpl_other_tags + ArrayList otherTags = otherTags(); + if (otherTags != null && otherTags.size() > 0) + metaInfo.add(new MetaInformation(simpl_other_tags.class, true, + otherTags.toArray())); + } + return metaInfo; + } + + @Override + public Object clone() { + ClassDescriptor cloned = null; + try { + cloned = (ClassDescriptor) super.clone(); + cloned.isCloned = true; + cloned.clonedFrom = this; + } catch (CloneNotSupportedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return cloned; + } + + public boolean isCloned() { + return isCloned; + } + + public ClassDescriptor getClonedFrom() { + return clonedFrom; + } + + public void setDescribedClassSimpleName(String describedClassSimpleName) { + this.describedClassSimpleName = describedClassSimpleName; + this.tagName = XMLTools.getXmlTagName(describedClassSimpleName, null); + } + + public void setDescribedClassPackageName(String describedClassPackageName) { + this.describedClassPackageName = describedClassPackageName; + } + + /** + * If this class is a generic class, such as MyClass<T>. + * + * Currently this is not implemented. Please update this javadoc when you + * implement it. + * + * @return + */ + public boolean isGenericClass() { + // TODO Auto-generated method stub + // NOT YET IMPLEMENTED! + return false; + } + + public void replace(FD oldFD, FD newFD) { + // for deserialization: + if (oldFD != null) + getAllFieldDescriptorsByTagNames().remove(oldFD.getTagName()); + getAllFieldDescriptorsByTagNames().put(newFD.getTagName(), newFD); + fieldDescriptorsByFieldName.put(newFD.getName(), newFD); + declaredFieldDescriptorsByFieldName.put(newFD.getName(), newFD); + // for serialization: + if (oldFD != null) { + replace(attributeFieldDescriptors, oldFD, newFD); + replace(elementFieldDescriptors, oldFD, newFD); + } + } + + private static void replace(List list, T oldVal, T newVal) { + if (list == null) + return; + int i = list.indexOf(oldVal); + if (i >= 0 && i < list.size()) { + list.set(i, newVal); + } + } + +} diff --git a/simplCore/src/ecologylab/serialization/ClassDescriptorIndexer.java b/simplCore/src/ecologylab/serialization/ClassDescriptorIndexer.java index be2f9051..37099bf2 100644 --- a/simplCore/src/ecologylab/serialization/ClassDescriptorIndexer.java +++ b/simplCore/src/ecologylab/serialization/ClassDescriptorIndexer.java @@ -1,149 +1,149 @@ -package ecologylab.serialization; - -import java.util.LinkedList; -import java.util.List; - -import javax.swing.event.ListSelectionEvent; - -import ecologylab.generic.ItemIndexPredicate; -import ecologylab.generic.MultiIndexer; - - -public class ClassDescriptorIndexer extends MultiIndexer> { - - - final class byTagName implements ItemIndexPredicate> - { - - @Override - public String GetIndexIdentifier() { - // TODO Auto-generated method stub - return "tagname"; - } - - @Override - public String ObtainIndex(ClassDescriptor item) { - // TODO Auto-generated method stub - return item.getTagName(); - } - } - - - final class byClassSimpleName implements ItemIndexPredicate> - { - - @Override - public String GetIndexIdentifier() { - // TODO Auto-generated method stub - return "javaclasssimplename"; - } - - @Override - public String ObtainIndex(ClassDescriptor item) { - // TODO Auto-generated method stub - return item.getDescribedClassSimpleName(); - } - - } - - final class byClassName implements ItemIndexPredicate> - { - - @Override - public String GetIndexIdentifier() { - // TODO Auto-generated method stub - return "javaclassname"; - } - - @Override - public String ObtainIndex(ClassDescriptor item) { - // TODO Auto-generated method stub - return null; - } - - } - - final class byTLVId implements ItemIndexPredicate> - { - - @Override - public String GetIndexIdentifier() { - // TODO Auto-generated method stub - return "tlvid"; - } - - @Override - public String ObtainIndex(ClassDescriptor item) { - // TODO Auto-generated method stub - return Integer.toString(item.getTagName().hashCode()); - } - - } - - final class bySimplName implements ItemIndexPredicate> { - - public bySimplName(){} - @Override - public String GetIndexIdentifier() { - // TODO Auto-generated method stub - return "simplname"; - } - - @Override - public String ObtainIndex(ClassDescriptor item) { - // TODO Auto-generated method stub - return item.getClassSimpleName(); - } - - } - - final class byObjectiveCName implements ItemIndexPredicate> - { - public byObjectiveCName(){} - @Override - public String GetIndexIdentifier() { - // TODO Auto-generated method stub - return "objc"; - } - - @Override - public String ObtainIndex(ClassDescriptor item) { - // TODO Autofgenerated method stub - return item.getObjectiveCTypeName(); - } - - } - - final class byBibtexType implements ItemIndexPredicate> - { - @Override - public String GetIndexIdentifier() { - // TODO Auto-generated method stub - return "bibtextype"; - } - - - @Override - public String ObtainIndex(ClassDescriptor item) { - // TODO Auto-generated method stub - return item.getBibtexType(); - } - } - - public List>> getIndexPredicates() { - List>> ourList = new LinkedList>>(); - - ourList.add(new byObjectiveCName()); - ourList.add(new bySimplName()); - ourList.add(new byBibtexType()); - ourList.add(new byClassName()); - ourList.add(new byClassSimpleName()); - ourList.add(new byTLVId()); - ourList.add(new byTagName()); - - //TODO: OH SHIT. MULTI INDEXING ... OTHER TAGS. MAKE INDEX RETURN LIST? :( - return ourList; - - } - -} +package ecologylab.serialization; + +import java.util.LinkedList; +import java.util.List; + +import javax.swing.event.ListSelectionEvent; + +import ecologylab.generic.ItemIndexPredicate; +import ecologylab.generic.MultiIndexer; + + +public class ClassDescriptorIndexer extends MultiIndexer> { + + + final class byTagName implements ItemIndexPredicate> + { + + @Override + public String GetIndexIdentifier() { + // TODO Auto-generated method stub + return "tagname"; + } + + @Override + public String ObtainIndex(ClassDescriptor item) { + // TODO Auto-generated method stub + return item.getTagName(); + } + } + + + final class byClassSimpleName implements ItemIndexPredicate> + { + + @Override + public String GetIndexIdentifier() { + // TODO Auto-generated method stub + return "javaclasssimplename"; + } + + @Override + public String ObtainIndex(ClassDescriptor item) { + // TODO Auto-generated method stub + return item.getDescribedClassSimpleName(); + } + + } + + final class byClassName implements ItemIndexPredicate> + { + + @Override + public String GetIndexIdentifier() { + // TODO Auto-generated method stub + return "javaclassname"; + } + + @Override + public String ObtainIndex(ClassDescriptor item) { + // TODO Auto-generated method stub + return null; + } + + } + + final class byTLVId implements ItemIndexPredicate> + { + + @Override + public String GetIndexIdentifier() { + // TODO Auto-generated method stub + return "tlvid"; + } + + @Override + public String ObtainIndex(ClassDescriptor item) { + // TODO Auto-generated method stub + return Integer.toString(item.getTagName().hashCode()); + } + + } + + final class bySimplName implements ItemIndexPredicate> { + + public bySimplName(){} + @Override + public String GetIndexIdentifier() { + // TODO Auto-generated method stub + return "simplname"; + } + + @Override + public String ObtainIndex(ClassDescriptor item) { + // TODO Auto-generated method stub + return item.getClassSimpleName(); + } + + } + + final class byObjectiveCName implements ItemIndexPredicate> + { + public byObjectiveCName(){} + @Override + public String GetIndexIdentifier() { + // TODO Auto-generated method stub + return "objc"; + } + + @Override + public String ObtainIndex(ClassDescriptor item) { + // TODO Autofgenerated method stub + return item.getObjectiveCTypeName(); + } + + } + + final class byBibtexType implements ItemIndexPredicate> + { + @Override + public String GetIndexIdentifier() { + // TODO Auto-generated method stub + return "bibtextype"; + } + + + @Override + public String ObtainIndex(ClassDescriptor item) { + // TODO Auto-generated method stub + return item.getBibtexType(); + } + } + + public List>> getIndexPredicates() { + List>> ourList = new LinkedList>>(); + + ourList.add(new byObjectiveCName()); + ourList.add(new bySimplName()); + ourList.add(new byBibtexType()); + ourList.add(new byClassName()); + ourList.add(new byClassSimpleName()); + ourList.add(new byTLVId()); + ourList.add(new byTagName()); + + //TODO: OH SHIT. MULTI INDEXING ... OTHER TAGS. MAKE INDEX RETURN LIST? :( + return ourList; + + } + +} diff --git a/simplCore/src/ecologylab/serialization/DescriptorBase.java b/simplCore/src/ecologylab/serialization/DescriptorBase.java index 888ac942..c0da96cb 100644 --- a/simplCore/src/ecologylab/serialization/DescriptorBase.java +++ b/simplCore/src/ecologylab/serialization/DescriptorBase.java @@ -1,100 +1,100 @@ -/** - * - */ -package ecologylab.serialization; - -import java.util.ArrayList; -import java.util.List; - -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.SimplBaseType; - -/** - * Common code for ClassDescriptor and FieldDescriptor. - * - * @author andruid - */ -@simpl_inherit -public abstract class DescriptorBase extends SimplBaseType -{ - - /** - * The tag name that this field is translated to XML with. For polymorphic fields, the value of - * this field is meaningless, except for wrapped collections and maps. - */ - @simpl_scalar - protected String tagName; - - /** - * Used to specify old translations, for backwards compatability. Never written. - */ - @simpl_nowrap - @simpl_collection("other_tag") - protected ArrayList otherTags; - - /** - * Documentation comment for a class or field. - */ - @simpl_scalar - protected String comment; - - protected List metaInfo; - - protected static IJavaParser javaParser; - - /** - * - */ - public DescriptorBase() - { - super(); - } - - public DescriptorBase(String tagName, String name) - { - this(tagName, name, null); - } - - public DescriptorBase(String tagName, String name, String comment) - { - super(name); - this.comment = comment; - this.tagName = tagName; - } - - /** - * NB: For polymorphic fields, the value of this field is meaningless, except for wrapped - * collections and maps. - * - * @return The tag name that this field is translated to XML with. - */ - public String getTagName() - { - return tagName; - } - - protected void setTagName(String tagName) - { - this.tagName = tagName; - } - - abstract public ArrayList otherTags(); - - /** - * - * @return the java doc comment - */ - public String getComment() - { - return comment; - } - - public static void setJavaParser(IJavaParser javaParser) - { - DescriptorBase.javaParser = javaParser; - } - -} +/** + * + */ +package ecologylab.serialization; + +import java.util.ArrayList; +import java.util.List; + +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.SimplBaseType; + +/** + * Common code for ClassDescriptor and FieldDescriptor. + * + * @author andruid + */ +@simpl_inherit +public abstract class DescriptorBase extends SimplBaseType +{ + + /** + * The tag name that this field is translated to XML with. For polymorphic fields, the value of + * this field is meaningless, except for wrapped collections and maps. + */ + @simpl_scalar + protected String tagName; + + /** + * Used to specify old translations, for backwards compatability. Never written. + */ + @simpl_nowrap + @simpl_collection("other_tag") + protected ArrayList otherTags; + + /** + * Documentation comment for a class or field. + */ + @simpl_scalar + protected String comment; + + protected List metaInfo; + + protected static IJavaParser javaParser; + + /** + * + */ + public DescriptorBase() + { + super(); + } + + public DescriptorBase(String tagName, String name) + { + this(tagName, name, null); + } + + public DescriptorBase(String tagName, String name, String comment) + { + super(name); + this.comment = comment; + this.tagName = tagName; + } + + /** + * NB: For polymorphic fields, the value of this field is meaningless, except for wrapped + * collections and maps. + * + * @return The tag name that this field is translated to XML with. + */ + public String getTagName() + { + return tagName; + } + + protected void setTagName(String tagName) + { + this.tagName = tagName; + } + + abstract public ArrayList otherTags(); + + /** + * + * @return the java doc comment + */ + public String getComment() + { + return comment; + } + + public static void setJavaParser(IJavaParser javaParser) + { + DescriptorBase.javaParser = javaParser; + } + +} diff --git a/simplCore/src/ecologylab/serialization/ElementState.java b/simplCore/src/ecologylab/serialization/ElementState.java index 3cb1687a..2db0639c 100644 --- a/simplCore/src/ecologylab/serialization/ElementState.java +++ b/simplCore/src/ecologylab/serialization/ElementState.java @@ -1,227 +1,227 @@ -package ecologylab.serialization; - -import java.util.HashMap; -import java.util.Stack; - -import ecologylab.generic.Debug; -import ecologylab.serialization.deserializers.ISimplDeserializationIn; -import ecologylab.serialization.deserializers.ISimplDeserializationPost; -import ecologylab.serialization.deserializers.ISimplDeserializationPre; -import ecologylab.serialization.serializers.ISimplSerializationPost; -import ecologylab.serialization.serializers.ISimplSerializationPre; - -public class ElementState extends Debug implements FieldTypes, - XMLTranslationExceptionTypes, ISimplSerializationPre, ISimplSerializationPost, - ISimplDeserializationPre, ISimplDeserializationPost, ISimplDeserializationIn -{ - - private boolean isRoot = false; - - /** - * Link for a DOM tree. should be removed - */ - transient PES parent; - - /** - * to handle objects with multiple parents this variable helps keep track of parents in - * deserializing graph - */ - Stack parents = null; - - /** - * Use for resolving getElementById() - */ - transient HashMap elementByIdMap; - - transient HashMap nestedNameSpaces; - - static protected final int ESTIMATE_CHARS_PER_FIELD = 80; - - /** - * Just-in time look-up tables to make translation be efficient. Allocated on a per class basis. - */ - transient private ClassDescriptor classDescriptor; - - /** - * Construct. Create a link to a root optimizations object. - */ - public ElementState() - { - } - - public TranslationContext createGraphContext() throws SIMPLTranslationException - { - TranslationContext graphContext = new TranslationContext(); - graphContext.resolveGraph(this); - isRoot = true; - return graphContext; - } - - /** - * The DOM classic accessor method. - * - * @return element in the tree rooted from this, whose id attrribute is as in the parameter. - * - */ - public ElementState getElementStateById(String id) - { - return this.elementByIdMap.get(id); - } - - /** - * @return the parent - */ - public PES parent() - { - // return (parent != null) ? parent : - // (parents != null && !parents.empty()) ? parents.firstElement() : - // null; - return parent; - } - - /** - * Set the parent of this, to create the tree structure. - * - * @param parent - */ - public void setParent(PES parent) - { - this.parent = parent; - } - - public ElementState getRoot() - { - ElementState parent = parent(); - return parent == null ? this : parent.getRoot(); - } - - /** - * Perform custom processing on the newly created child node, just before it is added to this. - *

- * This is part of depth-first traversal during translateFromXML(). - *

- * This, the default implementation, does nothing. Sub-classes may wish to override. - * - * @param foo - */ - protected void createChildHook(ElementState foo) - { - - } - - /** - * Clear data structures and references to enable garbage collecting of resources associated with - * this. - */ - public void recycle() - { - if (parent == null) - { // root state! - if (elementByIdMap != null) - { - elementByIdMap.clear(); - elementByIdMap = null; - } - } - else - parent = null; - - elementByIdMap = null; - if (nestedNameSpaces != null) - { - for (ElementState nns : nestedNameSpaces.values()) - { - if (nns != null) - nns.recycle(); - } - nestedNameSpaces.clear(); - nestedNameSpaces = null; - } - } - - /** - * Set-up referential chains for a newly born child of this. - * - * @param newParent - * @param ourClassDescriptor - * TODO - */ - public void setupInParent(ElementState newParent) - { - this.elementByIdMap = newParent.elementByIdMap; - this.manageParents(newParent); - } - - private void manageParents(ElementState parentES) - { - PES parentPES = (PES) parentES; - if (this.parent == null) - { - this.parent = parentPES; - } - else - { - if (this.parents == null) - { - this.parents = new Stack(); - this.parents.push(this.parent); - this.parents.push(parentPES); - } - else - { - this.parents.push(parentPES); - } - } - } - - /** - * @return Returns the optimizations. - */ - - public ClassDescriptor classDescriptor() - { - ClassDescriptor result = classDescriptor; - if (result == null) - { - result = ClassDescriptor.getClassDescriptor(this); - this.classDescriptor = result; - } - return result; - } - - @Override - public void serializationPostHook(TranslationContext translationContext) - { - // TODO Auto-generated method stub - - } - - @Override - public void serializationPreHook(TranslationContext translationContext) - { - // TODO Auto-generated method stub - - } - - @Override - public void deserializationPreHook(TranslationContext translationContext) - { - // TODO Auto-generated method stub - - } - - @Override - public void deserializationPostHook(TranslationContext translationContext, Object object) - { - // TODO Auto-generated method stub - - } - - @Override - public void deserializationInHook(TranslationContext translationContext) - { - // TODO Auto-generated method stub - - } - -} +package ecologylab.serialization; + +import java.util.HashMap; +import java.util.Stack; + +import ecologylab.generic.Debug; +import ecologylab.serialization.deserializers.ISimplDeserializationIn; +import ecologylab.serialization.deserializers.ISimplDeserializationPost; +import ecologylab.serialization.deserializers.ISimplDeserializationPre; +import ecologylab.serialization.serializers.ISimplSerializationPost; +import ecologylab.serialization.serializers.ISimplSerializationPre; + +public class ElementState extends Debug implements FieldTypes, + XMLTranslationExceptionTypes, ISimplSerializationPre, ISimplSerializationPost, + ISimplDeserializationPre, ISimplDeserializationPost, ISimplDeserializationIn +{ + + private boolean isRoot = false; + + /** + * Link for a DOM tree. should be removed + */ + transient PES parent; + + /** + * to handle objects with multiple parents this variable helps keep track of parents in + * deserializing graph + */ + Stack parents = null; + + /** + * Use for resolving getElementById() + */ + transient HashMap elementByIdMap; + + transient HashMap nestedNameSpaces; + + static protected final int ESTIMATE_CHARS_PER_FIELD = 80; + + /** + * Just-in time look-up tables to make translation be efficient. Allocated on a per class basis. + */ + transient private ClassDescriptor classDescriptor; + + /** + * Construct. Create a link to a root optimizations object. + */ + public ElementState() + { + } + + public TranslationContext createGraphContext() throws SIMPLTranslationException + { + TranslationContext graphContext = new TranslationContext(); + graphContext.resolveGraph(this); + isRoot = true; + return graphContext; + } + + /** + * The DOM classic accessor method. + * + * @return element in the tree rooted from this, whose id attrribute is as in the parameter. + * + */ + public ElementState getElementStateById(String id) + { + return this.elementByIdMap.get(id); + } + + /** + * @return the parent + */ + public PES parent() + { + // return (parent != null) ? parent : + // (parents != null && !parents.empty()) ? parents.firstElement() : + // null; + return parent; + } + + /** + * Set the parent of this, to create the tree structure. + * + * @param parent + */ + public void setParent(PES parent) + { + this.parent = parent; + } + + public ElementState getRoot() + { + ElementState parent = parent(); + return parent == null ? this : parent.getRoot(); + } + + /** + * Perform custom processing on the newly created child node, just before it is added to this. + *

+ * This is part of depth-first traversal during translateFromXML(). + *

+ * This, the default implementation, does nothing. Sub-classes may wish to override. + * + * @param foo + */ + protected void createChildHook(ElementState foo) + { + + } + + /** + * Clear data structures and references to enable garbage collecting of resources associated with + * this. + */ + public void recycle() + { + if (parent == null) + { // root state! + if (elementByIdMap != null) + { + elementByIdMap.clear(); + elementByIdMap = null; + } + } + else + parent = null; + + elementByIdMap = null; + if (nestedNameSpaces != null) + { + for (ElementState nns : nestedNameSpaces.values()) + { + if (nns != null) + nns.recycle(); + } + nestedNameSpaces.clear(); + nestedNameSpaces = null; + } + } + + /** + * Set-up referential chains for a newly born child of this. + * + * @param newParent + * @param ourClassDescriptor + * TODO + */ + public void setupInParent(ElementState newParent) + { + this.elementByIdMap = newParent.elementByIdMap; + this.manageParents(newParent); + } + + private void manageParents(ElementState parentES) + { + PES parentPES = (PES) parentES; + if (this.parent == null) + { + this.parent = parentPES; + } + else + { + if (this.parents == null) + { + this.parents = new Stack(); + this.parents.push(this.parent); + this.parents.push(parentPES); + } + else + { + this.parents.push(parentPES); + } + } + } + + /** + * @return Returns the optimizations. + */ + + public ClassDescriptor classDescriptor() + { + ClassDescriptor result = classDescriptor; + if (result == null) + { + result = ClassDescriptor.getClassDescriptor(this); + this.classDescriptor = result; + } + return result; + } + + @Override + public void serializationPostHook(TranslationContext translationContext) + { + // TODO Auto-generated method stub + + } + + @Override + public void serializationPreHook(TranslationContext translationContext) + { + // TODO Auto-generated method stub + + } + + @Override + public void deserializationPreHook(TranslationContext translationContext) + { + // TODO Auto-generated method stub + + } + + @Override + public void deserializationPostHook(TranslationContext translationContext, Object object) + { + // TODO Auto-generated method stub + + } + + @Override + public void deserializationInHook(TranslationContext translationContext) + { + // TODO Auto-generated method stub + + } + +} diff --git a/simplCore/src/ecologylab/serialization/ElementStateOrmBase.java b/simplCore/src/ecologylab/serialization/ElementStateOrmBase.java index d9a54843..f6065c10 100644 --- a/simplCore/src/ecologylab/serialization/ElementStateOrmBase.java +++ b/simplCore/src/ecologylab/serialization/ElementStateOrmBase.java @@ -1,24 +1,24 @@ -package ecologylab.serialization; - -/** - * a base class for GUI states, providing the default ORM id field. - * - * @author quyin - * - */ -public class ElementStateOrmBase extends ElementState -{ - - private long ormId; - - public long getOrmId() - { - return ormId; - } - - public void setOrmId(long ormId) - { - this.ormId = ormId; - } - -} +package ecologylab.serialization; + +/** + * a base class for GUI states, providing the default ORM id field. + * + * @author quyin + * + */ +public class ElementStateOrmBase extends ElementState +{ + + private long ormId; + + public long getOrmId() + { + return ormId; + } + + public void setOrmId(long ormId) + { + this.ormId = ormId; + } + +} diff --git a/simplCore/src/ecologylab/serialization/EnumerationDescriptor.java b/simplCore/src/ecologylab/serialization/EnumerationDescriptor.java index eea5f817..b27993de 100644 --- a/simplCore/src/ecologylab/serialization/EnumerationDescriptor.java +++ b/simplCore/src/ecologylab/serialization/EnumerationDescriptor.java @@ -1,475 +1,475 @@ -package ecologylab.serialization; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; - -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_scalar; - -public class EnumerationDescriptor extends DescriptorBase implements ISimplStringMarshaller { - - /** - * Gets an enumeration description for a given class. - * @param enumerationClass The given class to describe. - * @return An EnumerationDescription - * @throws SIMPLDescriptionException Whenever the described class has invalid aspects - */ - public static EnumerationDescriptor get(Class enumerationClass) throws SIMPLDescriptionException - { - // TODO: Add caching here at some point. - - EnumerationDescriptor ed = new EnumerationDescriptor(enumerationClass); - - if(isCustomValuedEnum(enumerationClass)) - { - // Remember: An enum is a collection of static constants of a type... - Object[] enumerationConstants = enumerationClass.getEnumConstants(); - - for(Object o : enumerationConstants) - { - String enumEntryName = ((Enum)o).toString(); - Integer enumEntryValue; - try - { - // We marshal this value in; sometimes, we need to reset the accessibility - enumEntryValue = (Integer)ed.getEnumerationCustomValueField().get(o); - // Interesting aside: It seems that on the first entry of an enumeration, we /always/ need to set accessibility - // But not on the second. Weird! - } - catch (IllegalArgumentException e) { - throw new SIMPLDescriptionException("Illegal argument exception while attempting to marshal entry value for enum entry: " + enumEntryName, e); - } - catch (IllegalAccessException e) - { - try{ - // Most of the time, we can set the field to accessible to overcome the IllegalAccessException - ed.getEnumerationCustomValueField().setAccessible(true); - enumEntryValue = (Integer)ed.getEnumerationCustomValueField().get(o); - } - catch(Exception w) - { - throw new SIMPLDescriptionException("Illegal access exception while attempting to marshal entry value for enum entry: " + enumEntryName, w); - } - } - - ed.getEnumerationEntries().add(new EnumerationEntry(enumEntryName, enumEntryValue)); - } - } - else - { - // Remember: An enum is a collection of static constants of a type... - Object[] enumerationConstants = enumerationClass.getEnumConstants(); - - for(Object o : enumerationConstants) - { - String enumEntryName = ((Enum)o).toString(); - - ed.getEnumerationEntries().add(new EnumerationEntry(enumEntryName)); - } - } - - return ed; - } - - /** - * Initialize the basic data structures in the EnumerationDescription - */ - private void basicInitialization() - { - this.enumerationEntries = new LinkedList(); - this.metaInfo = new LinkedList(); - this.otherTags = new ArrayList(); - } - - /** - * This constructor is primarily for the sake of SIMPL serialization; you probably don't want to use it. - */ - public EnumerationDescriptor() - { - basicInitialization(); - } - - /** - * Creates an EnumerationDescription from a Class... Does not add the EnumerationEntries - * (Leave that to .Get() which will cache the EnumreationDescriptions) - * @param describedEnum - * @throws SIMPLDescriptionException - */ - private EnumerationDescriptor(Class describedEnum) throws SIMPLDescriptionException - { - super(XMLTools.getXmlTagName(describedEnum, null), describedEnum.getSimpleName()); - basicInitialization(); - - if(describedEnum.isEnum()) - { - this.enumerationClass = describedEnum; - this.enumerationName = describedEnum.getName(); - this.packageName = describedEnum.getPackage().getName(); - - if(isCustomValuedEnum(describedEnum)) - { - List enumFields = getEnumerationFields(describedEnum); - - if(enumFields.size() == 1) - { - Field theField = enumFields.get(0); - - if(!(theField.getType().equals(Integer.class) || theField.getType().equals(int.class))) - { - throw new SIMPLDescriptionException("To facilitate cross-platform compatability, any custom valued enumeration must be an Integer or an int type."); - } - else - { - if(theField.getAnnotation(simpl_scalar.class) != null) - { - this.enumerationCustomValueField = theField; - } - else - { - throw new SIMPLDescriptionException("Error on: " + describedEnum.getName() + " The single field of an enumeration type should be annotated with the simpl_scalar type."); - } - } - } - else - { - // In java, our enumerations can be super fancy... not the case in most languages. (specifically statically typed languages w/ enum types) - throw new SIMPLDescriptionException("To facilitate cross-platform compatibility, any custom-valued enumeration must have only a single value field."); - } - } - }else{ - throw new SIMPLDescriptionException("Cannot create an enumeration description for a non-enumeration type."); - } - } - - @simpl_scalar - private String packageName; - - @simpl_scalar - private String enumerationName; - - /** - * The class that represents the enumeration class. - */ - private Class enumerationClass; - - /** - * The field that represents the custom value for this enumeration. - */ - private Field enumerationCustomValueField; - - - public Field getEnumerationCustomValueField() { - return enumerationCustomValueField; - } - - /** - * A list of entires in this given enumeration. - */ - @simpl_collection("entry") - private List enumerationEntries; - - - public Class getEnumerationClass() { - return enumerationClass; - } - - public void setEnumerationClass(Class enumerationClass) { - this.enumerationClass = enumerationClass; - } - - public List getEnumerationEntries() { - return enumerationEntries; - } - - public void setEnumerationEntries(List enumerationEntries) { - this.enumerationEntries = enumerationEntries; - } - - @Override - public ArrayList otherTags() { - // TODO Auto-generated method stub - return new ArrayList(); - } - - @Override - public String getJavaTypeName() { - // TODO Auto-generated method stub - return enumerationName; - } - - @Override - public String getCSharpTypeName() { - // TODO Auto-generated method stub - return enumerationName; - } - - @Override - public String getCSharpNamespace() { - // TODO Auto-generated method stub - return packageName; - } - - @Override - public String getObjectiveCTypeName() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getDbTypeName() { - // TODO Auto-generated method stub - return null ; - } - - /** - * Determines if this enumeration contains an entry with the given entry name - * @param entryName Name of the entry (case sensitive) - * @return True if the entry is in the list of entries - */ - public boolean containsEntry(String entryName) - { - for(EnumerationEntry ee : this.enumerationEntries) - { - if(ee.getName().equals(entryName)) - { - return true; - } - } - - return false; - } - - private Class fetchEnumClass() - { - if(this.enumerationClass == null) - { - // let's fetch a class! :3 - try{ - Class theClass = Class.forName(this.getJavaTypeName()); - this.enumerationClass = theClass; - } - catch(Exception e) - { - return null; - } - } - // TODO: Standard simpl code for ressurecting the class of a simpl descriptor / field? - return this.enumerationClass; - } - - private HashMap> enumNameToEnumValueHash = null; - private HashMap> enumIntegerToEnumValueHash = null; - - /** - * Fetches the Enum Value from the name of a given enrty, or null if the given string does not correspond to a value. - * @param string The entry name to retrieve - * @return The Enum value for the entry name, or null if none exists. - */ - public Enum getEntryEnumValue(String string) { - - // lazy initialize some underlying hashes from the data we have. - if(enumNameToEnumValueHash == null) - { - if(this.enumerationClass == null) - { - this.enumerationClass = fetchEnumClass(); - } - this.enumNameToEnumValueHash = fetchEnumNameToEnumValueHash(); - } - - return this.enumNameToEnumValueHash.get(string); - } - - public Enum getEntryEnumFromValue(Integer value) - { - return this.getEntryEnumValue(this.fetchEnumValueToEnumName().get(value)); - } - - /** - * Fetches a name to EnumValue hash, lazy initializes behind the scenes. - * @return - */ - private HashMap> fetchEnumNameToEnumValueHash() { - if(this.enumerationClass == null) - { - this.enumerationClass = fetchEnumClass(); - } - - HashMap> ourHash = new HashMap>(); - - for(Object o : this.enumerationClass.getEnumConstants()) - { - Enum aValue = (Enum)o; - String aName = aValue.toString(); - ourHash.put(aName, aValue); - } - - return ourHash; - } - - private HashMap fetchEnumNameToEnumIntegerValue() { - - HashMap ourHash = new HashMap(); - - if(isCustomValuedEnum(fetchEnumClass())) - { - for(EnumerationEntry ee : this.enumerationEntries) - { - ourHash.put(ee.getName(), ee.getValue()); - } - } - - return ourHash; - } - - private HashMap fetchEnumValueToEnumName() - { - HashMap ourHash = new HashMap(); - - if(isCustomValuedEnum(fetchEnumClass())) - { - for(EnumerationEntry ee : this.enumerationEntries) - { - ourHash.put(ee.getValue(), ee.getName()); - } - } - - return ourHash; - } - - - - /** - * Filters out all extraneous fields and gets only enumeration-entry level fields - * @param enumClass - * @return - */ - private static List getEnumerationFields(Class enumClass) - { - List filteredFields = new LinkedList(); - for(Field f:enumClass.getDeclaredFields()) - { - if(f.isEnumConstant()) - { - continue; // exclude enum constants - } - - if(Modifier.isStatic(f.getModifiers())) - { - continue; // exclude static - } - - filteredFields.add(f); - } - return filteredFields; - } - - /** - * Determines if a given class represents a "Custom Valued" enumeration - * @param enumClass - * @return - */ - public static boolean isCustomValuedEnum(Class enumClass) { - if(enumClass.isEnum()) - { - // So, an enumeration creates public static final fields for each entry - // and a private static final values() field... - // any additional fields have different signatures; so let's filter out all of those other fields and procede accordingly. - - List filteredFields = getEnumerationFields(enumClass); - - if(filteredFields.isEmpty()) - { - return false; - } - else - { - return true; - } - }else{ - return false; // not even an enum to begin with! - } - } - - /** - * Gets the integer value that corresponds to a custom-valued enumeration - * @param string Entry name - * @return Custom value - */ - public Integer getEntryEnumIntegerValue(String string) { - return fetchEnumNameToEnumIntegerValue().get(string); - } - - @Override - /** - * Marshals a given Object (an enumeration, in our case) to a string representation. - */ - public String marshal(Object object) throws SIMPLTranslationException{ - // TODO Auto-generated method stub - if(object == null) - { - throw new SIMPLTranslationException(new SimplIssue("Should not attempt to marshal null values.", null, object)); - } - - if(object.getClass().isEnum()) - { - if(object.getClass().equals(this.fetchEnumClass())) - { - //We have a valid object! Let's do this! - return object.toString(); // Hehehe. This should do the trick. - // Marshalling enums here is super trivial because toString() is guarenteed to return the name. - // Unmarshalling will be a bit more tricksy... but not by much. - } - else - { - throw new SIMPLTranslationException(new SimplIssue("Could not marshal because enumeration class was not the same as that in description. Was: "+ object.getClass().getName(), null, object)); - } - } - else - { - throw new SIMPLTranslationException(new SimplIssue("Could not marshal a non-enumeration type... was: " + object.getClass().getName(), null, object)); - } - } - - @Override - public Object unmarshal(String string) throws SIMPLTranslationException{ - // TODO Auto-generated method stub - if(string == null || string.isEmpty()) - { - throw new SIMPLTranslationException(new SimplIssue("Could not unmarshal a null or empty string!", string, null)); - } - - if(this.containsEntry(string)) - { - // We have this entry! Let's try to get it. - return this.getEntryEnumValue(string); - } - else - { - // Can we convert the string to an integer? If yes: try to marshal by value... - // otherwise, it's not in here! - try - { - Integer enumValue = Integer.parseInt(string); - Object value = this.getEntryEnumFromValue(enumValue); - if(value == null) - { - throw new SIMPLTranslationException(new SimplIssue("No enumeration entry exists with given value!", string, null)); - } - else - { - return value; - } - } - catch(NumberFormatException nfe) - { - throw new SIMPLTranslationException(new SimplIssue("Could not find the string value in the enumeration!", string, null)); - } - } - - } -} +package ecologylab.serialization; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_scalar; + +public class EnumerationDescriptor extends DescriptorBase implements ISimplStringMarshaller { + + /** + * Gets an enumeration description for a given class. + * @param enumerationClass The given class to describe. + * @return An EnumerationDescription + * @throws SIMPLDescriptionException Whenever the described class has invalid aspects + */ + public static EnumerationDescriptor get(Class enumerationClass) throws SIMPLDescriptionException + { + // TODO: Add caching here at some point. + + EnumerationDescriptor ed = new EnumerationDescriptor(enumerationClass); + + if(isCustomValuedEnum(enumerationClass)) + { + // Remember: An enum is a collection of static constants of a type... + Object[] enumerationConstants = enumerationClass.getEnumConstants(); + + for(Object o : enumerationConstants) + { + String enumEntryName = ((Enum)o).toString(); + Integer enumEntryValue; + try + { + // We marshal this value in; sometimes, we need to reset the accessibility + enumEntryValue = (Integer)ed.getEnumerationCustomValueField().get(o); + // Interesting aside: It seems that on the first entry of an enumeration, we /always/ need to set accessibility + // But not on the second. Weird! + } + catch (IllegalArgumentException e) { + throw new SIMPLDescriptionException("Illegal argument exception while attempting to marshal entry value for enum entry: " + enumEntryName, e); + } + catch (IllegalAccessException e) + { + try{ + // Most of the time, we can set the field to accessible to overcome the IllegalAccessException + ed.getEnumerationCustomValueField().setAccessible(true); + enumEntryValue = (Integer)ed.getEnumerationCustomValueField().get(o); + } + catch(Exception w) + { + throw new SIMPLDescriptionException("Illegal access exception while attempting to marshal entry value for enum entry: " + enumEntryName, w); + } + } + + ed.getEnumerationEntries().add(new EnumerationEntry(enumEntryName, enumEntryValue)); + } + } + else + { + // Remember: An enum is a collection of static constants of a type... + Object[] enumerationConstants = enumerationClass.getEnumConstants(); + + for(Object o : enumerationConstants) + { + String enumEntryName = ((Enum)o).toString(); + + ed.getEnumerationEntries().add(new EnumerationEntry(enumEntryName)); + } + } + + return ed; + } + + /** + * Initialize the basic data structures in the EnumerationDescription + */ + private void basicInitialization() + { + this.enumerationEntries = new LinkedList(); + this.metaInfo = new LinkedList(); + this.otherTags = new ArrayList(); + } + + /** + * This constructor is primarily for the sake of SIMPL serialization; you probably don't want to use it. + */ + public EnumerationDescriptor() + { + basicInitialization(); + } + + /** + * Creates an EnumerationDescription from a Class... Does not add the EnumerationEntries + * (Leave that to .Get() which will cache the EnumreationDescriptions) + * @param describedEnum + * @throws SIMPLDescriptionException + */ + private EnumerationDescriptor(Class describedEnum) throws SIMPLDescriptionException + { + super(XMLTools.getXmlTagName(describedEnum, null), describedEnum.getSimpleName()); + basicInitialization(); + + if(describedEnum.isEnum()) + { + this.enumerationClass = describedEnum; + this.enumerationName = describedEnum.getName(); + this.packageName = describedEnum.getPackage().getName(); + + if(isCustomValuedEnum(describedEnum)) + { + List enumFields = getEnumerationFields(describedEnum); + + if(enumFields.size() == 1) + { + Field theField = enumFields.get(0); + + if(!(theField.getType().equals(Integer.class) || theField.getType().equals(int.class))) + { + throw new SIMPLDescriptionException("To facilitate cross-platform compatability, any custom valued enumeration must be an Integer or an int type."); + } + else + { + if(theField.getAnnotation(simpl_scalar.class) != null) + { + this.enumerationCustomValueField = theField; + } + else + { + throw new SIMPLDescriptionException("Error on: " + describedEnum.getName() + " The single field of an enumeration type should be annotated with the simpl_scalar type."); + } + } + } + else + { + // In java, our enumerations can be super fancy... not the case in most languages. (specifically statically typed languages w/ enum types) + throw new SIMPLDescriptionException("To facilitate cross-platform compatibility, any custom-valued enumeration must have only a single value field."); + } + } + }else{ + throw new SIMPLDescriptionException("Cannot create an enumeration description for a non-enumeration type."); + } + } + + @simpl_scalar + private String packageName; + + @simpl_scalar + private String enumerationName; + + /** + * The class that represents the enumeration class. + */ + private Class enumerationClass; + + /** + * The field that represents the custom value for this enumeration. + */ + private Field enumerationCustomValueField; + + + public Field getEnumerationCustomValueField() { + return enumerationCustomValueField; + } + + /** + * A list of entires in this given enumeration. + */ + @simpl_collection("entry") + private List enumerationEntries; + + + public Class getEnumerationClass() { + return enumerationClass; + } + + public void setEnumerationClass(Class enumerationClass) { + this.enumerationClass = enumerationClass; + } + + public List getEnumerationEntries() { + return enumerationEntries; + } + + public void setEnumerationEntries(List enumerationEntries) { + this.enumerationEntries = enumerationEntries; + } + + @Override + public ArrayList otherTags() { + // TODO Auto-generated method stub + return new ArrayList(); + } + + @Override + public String getJavaTypeName() { + // TODO Auto-generated method stub + return enumerationName; + } + + @Override + public String getCSharpTypeName() { + // TODO Auto-generated method stub + return enumerationName; + } + + @Override + public String getCSharpNamespace() { + // TODO Auto-generated method stub + return packageName; + } + + @Override + public String getObjectiveCTypeName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getDbTypeName() { + // TODO Auto-generated method stub + return null ; + } + + /** + * Determines if this enumeration contains an entry with the given entry name + * @param entryName Name of the entry (case sensitive) + * @return True if the entry is in the list of entries + */ + public boolean containsEntry(String entryName) + { + for(EnumerationEntry ee : this.enumerationEntries) + { + if(ee.getName().equals(entryName)) + { + return true; + } + } + + return false; + } + + private Class fetchEnumClass() + { + if(this.enumerationClass == null) + { + // let's fetch a class! :3 + try{ + Class theClass = Class.forName(this.getJavaTypeName()); + this.enumerationClass = theClass; + } + catch(Exception e) + { + return null; + } + } + // TODO: Standard simpl code for ressurecting the class of a simpl descriptor / field? + return this.enumerationClass; + } + + private HashMap> enumNameToEnumValueHash = null; + private HashMap> enumIntegerToEnumValueHash = null; + + /** + * Fetches the Enum Value from the name of a given enrty, or null if the given string does not correspond to a value. + * @param string The entry name to retrieve + * @return The Enum value for the entry name, or null if none exists. + */ + public Enum getEntryEnumValue(String string) { + + // lazy initialize some underlying hashes from the data we have. + if(enumNameToEnumValueHash == null) + { + if(this.enumerationClass == null) + { + this.enumerationClass = fetchEnumClass(); + } + this.enumNameToEnumValueHash = fetchEnumNameToEnumValueHash(); + } + + return this.enumNameToEnumValueHash.get(string); + } + + public Enum getEntryEnumFromValue(Integer value) + { + return this.getEntryEnumValue(this.fetchEnumValueToEnumName().get(value)); + } + + /** + * Fetches a name to EnumValue hash, lazy initializes behind the scenes. + * @return + */ + private HashMap> fetchEnumNameToEnumValueHash() { + if(this.enumerationClass == null) + { + this.enumerationClass = fetchEnumClass(); + } + + HashMap> ourHash = new HashMap>(); + + for(Object o : this.enumerationClass.getEnumConstants()) + { + Enum aValue = (Enum)o; + String aName = aValue.toString(); + ourHash.put(aName, aValue); + } + + return ourHash; + } + + private HashMap fetchEnumNameToEnumIntegerValue() { + + HashMap ourHash = new HashMap(); + + if(isCustomValuedEnum(fetchEnumClass())) + { + for(EnumerationEntry ee : this.enumerationEntries) + { + ourHash.put(ee.getName(), ee.getValue()); + } + } + + return ourHash; + } + + private HashMap fetchEnumValueToEnumName() + { + HashMap ourHash = new HashMap(); + + if(isCustomValuedEnum(fetchEnumClass())) + { + for(EnumerationEntry ee : this.enumerationEntries) + { + ourHash.put(ee.getValue(), ee.getName()); + } + } + + return ourHash; + } + + + + /** + * Filters out all extraneous fields and gets only enumeration-entry level fields + * @param enumClass + * @return + */ + private static List getEnumerationFields(Class enumClass) + { + List filteredFields = new LinkedList(); + for(Field f:enumClass.getDeclaredFields()) + { + if(f.isEnumConstant()) + { + continue; // exclude enum constants + } + + if(Modifier.isStatic(f.getModifiers())) + { + continue; // exclude static + } + + filteredFields.add(f); + } + return filteredFields; + } + + /** + * Determines if a given class represents a "Custom Valued" enumeration + * @param enumClass + * @return + */ + public static boolean isCustomValuedEnum(Class enumClass) { + if(enumClass.isEnum()) + { + // So, an enumeration creates public static final fields for each entry + // and a private static final values() field... + // any additional fields have different signatures; so let's filter out all of those other fields and procede accordingly. + + List filteredFields = getEnumerationFields(enumClass); + + if(filteredFields.isEmpty()) + { + return false; + } + else + { + return true; + } + }else{ + return false; // not even an enum to begin with! + } + } + + /** + * Gets the integer value that corresponds to a custom-valued enumeration + * @param string Entry name + * @return Custom value + */ + public Integer getEntryEnumIntegerValue(String string) { + return fetchEnumNameToEnumIntegerValue().get(string); + } + + @Override + /** + * Marshals a given Object (an enumeration, in our case) to a string representation. + */ + public String marshal(Object object) throws SIMPLTranslationException{ + // TODO Auto-generated method stub + if(object == null) + { + throw new SIMPLTranslationException(new SimplIssue("Should not attempt to marshal null values.", null, object)); + } + + if(object.getClass().isEnum()) + { + if(object.getClass().equals(this.fetchEnumClass())) + { + //We have a valid object! Let's do this! + return object.toString(); // Hehehe. This should do the trick. + // Marshalling enums here is super trivial because toString() is guarenteed to return the name. + // Unmarshalling will be a bit more tricksy... but not by much. + } + else + { + throw new SIMPLTranslationException(new SimplIssue("Could not marshal because enumeration class was not the same as that in description. Was: "+ object.getClass().getName(), null, object)); + } + } + else + { + throw new SIMPLTranslationException(new SimplIssue("Could not marshal a non-enumeration type... was: " + object.getClass().getName(), null, object)); + } + } + + @Override + public Object unmarshal(String string) throws SIMPLTranslationException{ + // TODO Auto-generated method stub + if(string == null || string.isEmpty()) + { + throw new SIMPLTranslationException(new SimplIssue("Could not unmarshal a null or empty string!", string, null)); + } + + if(this.containsEntry(string)) + { + // We have this entry! Let's try to get it. + return this.getEntryEnumValue(string); + } + else + { + // Can we convert the string to an integer? If yes: try to marshal by value... + // otherwise, it's not in here! + try + { + Integer enumValue = Integer.parseInt(string); + Object value = this.getEntryEnumFromValue(enumValue); + if(value == null) + { + throw new SIMPLTranslationException(new SimplIssue("No enumeration entry exists with given value!", string, null)); + } + else + { + return value; + } + } + catch(NumberFormatException nfe) + { + throw new SIMPLTranslationException(new SimplIssue("Could not find the string value in the enumeration!", string, null)); + } + } + + } +} diff --git a/simplCore/src/ecologylab/serialization/EnumerationEntry.java b/simplCore/src/ecologylab/serialization/EnumerationEntry.java index 5dac2961..e9704cba 100644 --- a/simplCore/src/ecologylab/serialization/EnumerationEntry.java +++ b/simplCore/src/ecologylab/serialization/EnumerationEntry.java @@ -1,52 +1,52 @@ -package ecologylab.serialization; - -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * A class to represent entries in an enumeration - * @author tom - * - */ -public class EnumerationEntry { - - /** - * The name of the entry. - */ - @simpl_scalar - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getValue() { - return value; - } - - public void setValue(Integer value) { - this.value = value; - } - - /** - * The integer value of the entry; may not be set if the compiler is delegated to that task. - */ - @simpl_scalar - private Integer value; - - public EnumerationEntry(){} - - public EnumerationEntry(String name) - { - this.name = name; - } - - public EnumerationEntry(String name, Integer value) - { - this.name = name; - this.value = value; - } -} +package ecologylab.serialization; + +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * A class to represent entries in an enumeration + * @author tom + * + */ +public class EnumerationEntry { + + /** + * The name of the entry. + */ + @simpl_scalar + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getValue() { + return value; + } + + public void setValue(Integer value) { + this.value = value; + } + + /** + * The integer value of the entry; may not be set if the compiler is delegated to that task. + */ + @simpl_scalar + private Integer value; + + public EnumerationEntry(){} + + public EnumerationEntry(String name) + { + this.name = name; + } + + public EnumerationEntry(String name, Integer value) + { + this.name = name; + this.value = value; + } +} diff --git a/simplCore/src/ecologylab/serialization/FieldDescriptor.java b/simplCore/src/ecologylab/serialization/FieldDescriptor.java index 62a0ebc0..0f108a17 100644 --- a/simplCore/src/ecologylab/serialization/FieldDescriptor.java +++ b/simplCore/src/ecologylab/serialization/FieldDescriptor.java @@ -401,9 +401,7 @@ public EnumerationDescriptor getEnumerationDescriptor() */ private boolean derivePolymorphicDescriptors(Field field) { - // @xml_scope - final simpl_scope scopeAnnotationObj = field.getAnnotation(simpl_scope.class); - final String scopeAnnotation = (scopeAnnotationObj == null) ? null : scopeAnnotationObj.value(); + final String scopeAnnotation = getScopeName(field); if (scopeAnnotation != null && scopeAnnotation.length() > 0) { @@ -427,6 +425,13 @@ private boolean derivePolymorphicDescriptors(Field field) return polymorphClassDescriptors != null; } + private static String getScopeName(Field field) + { + final simpl_scope scopeAnnotationObj = field.getAnnotation(simpl_scope.class); + final String scopeAnnotation = (scopeAnnotationObj == null) ? null : scopeAnnotationObj.value(); + return scopeAnnotation; + } + /** * Register a ClassDescriptor that is polymorphically engaged with this field. * @@ -440,6 +445,10 @@ protected void registerPolymorphicDescriptor(ClassDescriptor classDescriptor) String classTag = classDescriptor.getTagName(); polymorphClassDescriptors.put(classTag, classDescriptor); tlvClassDescriptors.put(classTag.hashCode(), classDescriptor); + if (classDescriptor.getDescribedClass() != null) + { + polymorphClasses.put(classTag, classDescriptor.getDescribedClass()); + } ArrayList otherTags = classDescriptor.otherTags(); if (otherTags != null) @@ -465,6 +474,10 @@ private boolean resolveScopeAnnotation(final String scopeAnnotation) { println(scopeAnnotation); SimplTypesScope scope = SimplTypesScope.get(scopeAnnotation); + if (scope == null) + { // syntactic sugar on name of scope + scope = SimplTypesScope.get(scopeAnnotation + "_types_scope"); + } if (scope != null) { Collection> scopeClassDescriptors = scope @@ -472,10 +485,7 @@ private boolean resolveScopeAnnotation(final String scopeAnnotation) initPolymorphClassDescriptorsArrayList(scopeClassDescriptors.size()); for (ClassDescriptor classDescriptor : scopeClassDescriptors) { - String tagName = classDescriptor.getTagName(); - polymorphClassDescriptors.put(tagName, classDescriptor); - polymorphClasses.put(tagName, classDescriptor.getDescribedClass()); - tlvClassDescriptors.put(tagName.hashCode(), classDescriptor); + registerPolymorphicDescriptor(classDescriptor); } } else @@ -484,6 +494,13 @@ private boolean resolveScopeAnnotation(final String scopeAnnotation) } return scope != null; } + + public void reevaluateScopeAnnotation() + { + String scope = getScopeName(field); + SimplTypesScope.get(scope).clearCachedClassDescriptors(); + resolveScopeAnnotation(scope); + } /** * Generate tag -> class mappings for a @serial_scope declaration. @@ -1128,7 +1145,8 @@ public Map getMap(Object context) public Collection getCollection(Object context) { - return (Collection) ReflectionTools.getFieldValue(context, field); + Object fieldValue = ReflectionTools.getFieldValue(context, field); + return fieldValue instanceof Collection ? (Collection) fieldValue : null; } public boolean isMixin() diff --git a/simplCore/src/ecologylab/serialization/FieldType.java b/simplCore/src/ecologylab/serialization/FieldType.java index 58a64105..c424326f 100644 --- a/simplCore/src/ecologylab/serialization/FieldType.java +++ b/simplCore/src/ecologylab/serialization/FieldType.java @@ -1,72 +1,72 @@ -package ecologylab.serialization; - -import ecologylab.serialization.annotations.simpl_scalar; - -public enum FieldType { - - UNSET_TYPE(-999), - BAD_FIELD(-99), - IGNORED_ATTRIBUTE(-1), - SCALAR(0x12), - COMPOSITE_ELEMENT(3), - /** - * This means that we don't bother to parse the element, because the programmer developing - * ElementState subclasses did not bother to create fields that use it. - */ - IGNORED_ELEMENT(-3), - COLLECTION_ELEMENT(4), - COLLECTION_SCALAR(5), - MAP_ELEMENT(6), - MAP_SCALAR(7), - WRAPPER(0x0a), - PSEUDO_FIELD_DESCRIPTOR(0x0d), - NAMESPACE_IGNORED_ELEMENT(-2), - XMLNS_ATTRIBUTE(0x0e), - XMLNS_IGNORED(0x0f), - NAME_SPACE_MASK(0x10), - /** - * These are all masked; this is a legacy decision we're carrying over. - */ - NAMESPACE_TRIAL_ELEMENT(NAME_SPACE_MASK.getTypeID()), - NAME_SPACE_SCALAR(NAME_SPACE_MASK.getTypeID() + SCALAR.getTypeID()), - NAME_SPACE_NESTED_ELEMENT(NAME_SPACE_MASK.getTypeID()+ COMPOSITE_ELEMENT.getTypeID()); - - @simpl_scalar - private final int typeID; - - /** - * Gets the ID for the type. Currently really just for backward compatability with old code. - * @return - */ - public int getTypeID() - { - return this.typeID; - } - - /** - * Obtains a FieldTyep from a given ID - * @param typeID - * @return - */ - public static FieldType fromTypeID(int typeID) - { - for(FieldType ft : FieldType.values()) - { - if(ft.getTypeID()== typeID) - { - return ft; - } - } - // Just default to this. - return FieldType.BAD_FIELD; - } - - /** - * Creates a field type with a corresponding type ID number - * @param typeID - */ - FieldType(int typeID) - { - this.typeID = typeID; - } +package ecologylab.serialization; + +import ecologylab.serialization.annotations.simpl_scalar; + +public enum FieldType { + + UNSET_TYPE(-999), + BAD_FIELD(-99), + IGNORED_ATTRIBUTE(-1), + SCALAR(0x12), + COMPOSITE_ELEMENT(3), + /** + * This means that we don't bother to parse the element, because the programmer developing + * ElementState subclasses did not bother to create fields that use it. + */ + IGNORED_ELEMENT(-3), + COLLECTION_ELEMENT(4), + COLLECTION_SCALAR(5), + MAP_ELEMENT(6), + MAP_SCALAR(7), + WRAPPER(0x0a), + PSEUDO_FIELD_DESCRIPTOR(0x0d), + NAMESPACE_IGNORED_ELEMENT(-2), + XMLNS_ATTRIBUTE(0x0e), + XMLNS_IGNORED(0x0f), + NAME_SPACE_MASK(0x10), + /** + * These are all masked; this is a legacy decision we're carrying over. + */ + NAMESPACE_TRIAL_ELEMENT(NAME_SPACE_MASK.getTypeID()), + NAME_SPACE_SCALAR(NAME_SPACE_MASK.getTypeID() + SCALAR.getTypeID()), + NAME_SPACE_NESTED_ELEMENT(NAME_SPACE_MASK.getTypeID()+ COMPOSITE_ELEMENT.getTypeID()); + + @simpl_scalar + private final int typeID; + + /** + * Gets the ID for the type. Currently really just for backward compatability with old code. + * @return + */ + public int getTypeID() + { + return this.typeID; + } + + /** + * Obtains a FieldTyep from a given ID + * @param typeID + * @return + */ + public static FieldType fromTypeID(int typeID) + { + for(FieldType ft : FieldType.values()) + { + if(ft.getTypeID()== typeID) + { + return ft; + } + } + // Just default to this. + return FieldType.BAD_FIELD; + } + + /** + * Creates a field type with a corresponding type ID number + * @param typeID + */ + FieldType(int typeID) + { + this.typeID = typeID; + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/FieldTypes.java b/simplCore/src/ecologylab/serialization/FieldTypes.java index 6833e481..7e77db04 100644 --- a/simplCore/src/ecologylab/serialization/FieldTypes.java +++ b/simplCore/src/ecologylab/serialization/FieldTypes.java @@ -1,55 +1,55 @@ -package ecologylab.serialization; - -public interface FieldTypes -{ - public static final int UNSET_TYPE = -999; - - /** - * This means we experienced an error while parsing. This should never happen. - */ - public static final int BAD_FIELD = -99; - - public static final int IGNORED_ATTRIBUTE = -1; - - public static final int SCALAR = 0x12; - - public static final int COMPOSITE_ELEMENT = 3; - - - - /** - * This means that we don't bother to parse the element, because the programmer developing - * ElementState subclasses did not bother to create fields that use it. - */ - public static final int IGNORED_ELEMENT = -3; - - public static final int COLLECTION_ELEMENT = 4; - - public static final int COLLECTION_SCALAR = 5; - - public static final int MAP_ELEMENT = 6; - - public static final int MAP_SCALAR = 7; - - - public static final int WRAPPER = 0x0a; - - public static final int PSEUDO_FIELD_DESCRIPTOR = 0x0d; - - public static final int NAMESPACE_IGNORED_ELEMENT = -2; - - public static final int XMLNS_ATTRIBUTE = 0x0e; - - public static final int XMLNS_IGNORED = 0x0f; - - public static final int NAME_SPACE_MASK = 0x10; - - public static final int NAMESPACE_TRIAL_ELEMENT = NAME_SPACE_MASK; - - public static final int NAME_SPACE_SCALAR = NAME_SPACE_MASK + SCALAR; - - public static final int NAME_SPACE_NESTED_ELEMENT = NAME_SPACE_MASK + COMPOSITE_ELEMENT; -// -// public static final int NAME_SPACE_LEAF_NODE = NAME_SPACE_MASK + LEAF; - -} +package ecologylab.serialization; + +public interface FieldTypes +{ + public static final int UNSET_TYPE = -999; + + /** + * This means we experienced an error while parsing. This should never happen. + */ + public static final int BAD_FIELD = -99; + + public static final int IGNORED_ATTRIBUTE = -1; + + public static final int SCALAR = 0x12; + + public static final int COMPOSITE_ELEMENT = 3; + + + + /** + * This means that we don't bother to parse the element, because the programmer developing + * ElementState subclasses did not bother to create fields that use it. + */ + public static final int IGNORED_ELEMENT = -3; + + public static final int COLLECTION_ELEMENT = 4; + + public static final int COLLECTION_SCALAR = 5; + + public static final int MAP_ELEMENT = 6; + + public static final int MAP_SCALAR = 7; + + + public static final int WRAPPER = 0x0a; + + public static final int PSEUDO_FIELD_DESCRIPTOR = 0x0d; + + public static final int NAMESPACE_IGNORED_ELEMENT = -2; + + public static final int XMLNS_ATTRIBUTE = 0x0e; + + public static final int XMLNS_IGNORED = 0x0f; + + public static final int NAME_SPACE_MASK = 0x10; + + public static final int NAMESPACE_TRIAL_ELEMENT = NAME_SPACE_MASK; + + public static final int NAME_SPACE_SCALAR = NAME_SPACE_MASK + SCALAR; + + public static final int NAME_SPACE_NESTED_ELEMENT = NAME_SPACE_MASK + COMPOSITE_ELEMENT; +// +// public static final int NAME_SPACE_LEAF_NODE = NAME_SPACE_MASK + LEAF; + +} diff --git a/simplCore/src/ecologylab/serialization/IJavaParser.java b/simplCore/src/ecologylab/serialization/IJavaParser.java index 4f2a9ed6..5146d2ca 100644 --- a/simplCore/src/ecologylab/serialization/IJavaParser.java +++ b/simplCore/src/ecologylab/serialization/IJavaParser.java @@ -1,20 +1,20 @@ -/** - * - */ -package ecologylab.serialization; - -import java.lang.reflect.Field; - -/** - * Interface for modularizing access to a Java Parser. - * - * @author andruid - */ -public interface IJavaParser -{ - - public String getJavaDocComment(Class thatClass); - - public String getJavaDocComment(Field field); - -} +/** + * + */ +package ecologylab.serialization; + +import java.lang.reflect.Field; + +/** + * Interface for modularizing access to a Java Parser. + * + * @author andruid + */ +public interface IJavaParser +{ + + public String getJavaDocComment(Class thatClass); + + public String getJavaDocComment(Field field); + +} diff --git a/simplCore/src/ecologylab/serialization/ISimplLanguage.java b/simplCore/src/ecologylab/serialization/ISimplLanguage.java index 9202a1c3..af4d75be 100644 --- a/simplCore/src/ecologylab/serialization/ISimplLanguage.java +++ b/simplCore/src/ecologylab/serialization/ISimplLanguage.java @@ -1,54 +1,54 @@ -package ecologylab.serialization; - -import java.util.Collection; - -/** - * An interface that represents a language supported by simpl; Should be part of a "language package" in - * future versions of s.im.pl. - * In general: Implementers of this interface represent the core unique aspects of names in a language. The class - * should presumably hold onto some list of reserved words, provide a check for those reserved words, and also provide - * means for translating from simpl cross platform names to the language's appropriate names (and back and forth). - * - * Testing heuristics: Random strings should probably never trigger the isReserved() checks, - * marshalling from cross-platform name to language name and back shoudl always return the same string. - * - */ -public interface ISimplLanguage { - - /** - * Polymoprhic methods will use some case-insensitive identifier to identify - * languages; this method returns this identifier. - * @return The language identifier for a language. - */ - String getLanguageIdentifier(); - - /** - * Obtains a list of reserved keywords for a given language. These words can often be found in a specification for - * the language. Some languages may offer words that are reserved in certain contexts... those should be included - * in this collection. - * @return A Collection of reserved keywords. - */ - Collection getReservedKeywords(); - - /** - * Determines if a given string is a reserved keyword in this language - * @param keyword The string to check - * @return True if the word is a reserved word. - */ - boolean isReservedKeyword(String keyword); - - /** - * Converts a string representing a simpl name (a cross platform name, if you will) to an idiomatic string in this language. - * @param simplName The simpl name to convert - * @return a language-specific name - * @throws SIMPLTranslationException if the name is a reserved name. - */ - String convertSimplNameToLanguageName(String simplName) throws SIMPLTranslationException; - - /** - * Converts a string represetning a language specific name to a simpl name (a cross platform name, if you will) - * @param lanugageName The language name - * @return A cross-platform name - */ - String convertLanguageNameToSimplName(String lanugageName) throws SIMPLTranslationException; -} +package ecologylab.serialization; + +import java.util.Collection; + +/** + * An interface that represents a language supported by simpl; Should be part of a "language package" in + * future versions of s.im.pl. + * In general: Implementers of this interface represent the core unique aspects of names in a language. The class + * should presumably hold onto some list of reserved words, provide a check for those reserved words, and also provide + * means for translating from simpl cross platform names to the language's appropriate names (and back and forth). + * + * Testing heuristics: Random strings should probably never trigger the isReserved() checks, + * marshalling from cross-platform name to language name and back shoudl always return the same string. + * + */ +public interface ISimplLanguage { + + /** + * Polymoprhic methods will use some case-insensitive identifier to identify + * languages; this method returns this identifier. + * @return The language identifier for a language. + */ + String getLanguageIdentifier(); + + /** + * Obtains a list of reserved keywords for a given language. These words can often be found in a specification for + * the language. Some languages may offer words that are reserved in certain contexts... those should be included + * in this collection. + * @return A Collection of reserved keywords. + */ + Collection getReservedKeywords(); + + /** + * Determines if a given string is a reserved keyword in this language + * @param keyword The string to check + * @return True if the word is a reserved word. + */ + boolean isReservedKeyword(String keyword); + + /** + * Converts a string representing a simpl name (a cross platform name, if you will) to an idiomatic string in this language. + * @param simplName The simpl name to convert + * @return a language-specific name + * @throws SIMPLTranslationException if the name is a reserved name. + */ + String convertSimplNameToLanguageName(String simplName) throws SIMPLTranslationException; + + /** + * Converts a string represetning a language specific name to a simpl name (a cross platform name, if you will) + * @param lanugageName The language name + * @return A cross-platform name + */ + String convertLanguageNameToSimplName(String lanugageName) throws SIMPLTranslationException; +} diff --git a/simplCore/src/ecologylab/serialization/ISimplStringFormat.java b/simplCore/src/ecologylab/serialization/ISimplStringFormat.java index cd772e53..e518ede8 100644 --- a/simplCore/src/ecologylab/serialization/ISimplStringFormat.java +++ b/simplCore/src/ecologylab/serialization/ISimplStringFormat.java @@ -1,25 +1,25 @@ -package ecologylab.serialization; - -/** - * A given format has accepted "escaping" and "unescaping" functionality... - * This interface represents this escaping and unescaping for a given format. - * It is governed by a basic heuristic that a round-trip from string -> escaped -> unescaped should return - * the original string. - * @author tom - * - */ -public interface ISimplStringFormat { - /** - * Escapes a string in this format. - * @param unescapedString Unescaped string to escape - * @return The escaped string - */ - String escape(String unescapedString); - - /** - * Unescapes a string in this format - * @param escapedString An escaped string - * @return The unescaped string - */ - String unescape(String escapedString); -} +package ecologylab.serialization; + +/** + * A given format has accepted "escaping" and "unescaping" functionality... + * This interface represents this escaping and unescaping for a given format. + * It is governed by a basic heuristic that a round-trip from string -> escaped -> unescaped should return + * the original string. + * @author tom + * + */ +public interface ISimplStringFormat { + /** + * Escapes a string in this format. + * @param unescapedString Unescaped string to escape + * @return The escaped string + */ + String escape(String unescapedString); + + /** + * Unescapes a string in this format + * @param escapedString An escaped string + * @return The unescaped string + */ + String unescape(String escapedString); +} diff --git a/simplCore/src/ecologylab/serialization/ISimplStringMarshaller.java b/simplCore/src/ecologylab/serialization/ISimplStringMarshaller.java index 472434f5..dc2879e0 100644 --- a/simplCore/src/ecologylab/serialization/ISimplStringMarshaller.java +++ b/simplCore/src/ecologylab/serialization/ISimplStringMarshaller.java @@ -1,13 +1,13 @@ -package ecologylab.serialization; - -/** - * Represents an interfaces for classes that can marshal - * a given object to a "Simpl" string representation and from a representation to an object. - * This has the implicit round-trip heuristic that an object marshalled to a string, then unmarshalled should be equviliant to the original object. - * @author tom - * - */ -public interface ISimplStringMarshaller { - String marshal(Object object) throws SIMPLTranslationException; - Object unmarshal(String string) throws SIMPLTranslationException; -} +package ecologylab.serialization; + +/** + * Represents an interfaces for classes that can marshal + * a given object to a "Simpl" string representation and from a representation to an object. + * This has the implicit round-trip heuristic that an object marshalled to a string, then unmarshalled should be equviliant to the original object. + * @author tom + * + */ +public interface ISimplStringMarshaller { + String marshal(Object object) throws SIMPLTranslationException; + Object unmarshal(String string) throws SIMPLTranslationException; +} diff --git a/simplCore/src/ecologylab/serialization/JSONTools.java b/simplCore/src/ecologylab/serialization/JSONTools.java index 7e9e476b..eaca4f67 100644 --- a/simplCore/src/ecologylab/serialization/JSONTools.java +++ b/simplCore/src/ecologylab/serialization/JSONTools.java @@ -1,56 +1,56 @@ -package ecologylab.serialization; - -import java.io.IOException; - -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; - -import ecologylab.generic.Debug; - -/** - * JSON related tools. - * - * @author quyin - * - */ -public class JSONTools -{ - - static JsonFactory factory = new JsonFactory(); - - /** - * Validate if an input JSON strong is valid. Empty strings or null values will be regarded as - * INVALID. - * - * @param jsonString - * @return true if and only if the input string is an non-empty valid JSON sequence. - */ - public static boolean validate(String jsonString) - { - if (jsonString == null) - return false; - - try - { - JsonParser parser = factory.createJsonParser(jsonString); - while (parser.nextToken() != null) - { - // no-op - } - return true; - } - catch (JsonParseException e) - { - Debug.warning(JSONTools.class, "json validation failed: " + e.getMessage()); - e.printStackTrace(); - } - catch (IOException e) - { - e.printStackTrace(); - } - - return false; - } - -} +package ecologylab.serialization; + +import java.io.IOException; + +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.JsonParser; + +import ecologylab.generic.Debug; + +/** + * JSON related tools. + * + * @author quyin + * + */ +public class JSONTools +{ + + static JsonFactory factory = new JsonFactory(); + + /** + * Validate if an input JSON strong is valid. Empty strings or null values will be regarded as + * INVALID. + * + * @param jsonString + * @return true if and only if the input string is an non-empty valid JSON sequence. + */ + public static boolean validate(String jsonString) + { + if (jsonString == null) + return false; + + try + { + JsonParser parser = factory.createJsonParser(jsonString); + while (parser.nextToken() != null) + { + // no-op + } + return true; + } + catch (JsonParseException e) + { + Debug.warning(JSONTools.class, "json validation failed: " + e.getMessage()); + e.printStackTrace(); + } + catch (IOException e) + { + e.printStackTrace(); + } + + return false; + } + +} diff --git a/simplCore/src/ecologylab/serialization/JavaLanguage.java b/simplCore/src/ecologylab/serialization/JavaLanguage.java index 60ebc612..add56f6a 100644 --- a/simplCore/src/ecologylab/serialization/JavaLanguage.java +++ b/simplCore/src/ecologylab/serialization/JavaLanguage.java @@ -1,94 +1,94 @@ -package ecologylab.serialization; - -import java.util.Collection; -import java.util.HashMap; - -public class JavaLanguage implements ISimplLanguage{ - - private static HashMap keywords = new HashMap(); - - static - { - keywords.put("abstract", "abstract"); - keywords.put("continue","continue"); - keywords.put("for","for"); - keywords.put("new","new"); - keywords.put("switch","switch"); - keywords.put("assert","assert"); - keywords.put("default","default"); - keywords.put("package","package"); - keywords.put("synchronized","synchronized"); - keywords.put("boolean","boolean"); - keywords.put("do","do"); - keywords.put("if","if"); - keywords.put("private","private"); - keywords.put("this","this"); - keywords.put("break","break"); - keywords.put("double","double"); - keywords.put("implements","implements"); - keywords.put("protected","protected"); - keywords.put("throw","throw"); - keywords.put("byte","byte"); - keywords.put("else","else"); - keywords.put("import","import"); - keywords.put("public","public"); - keywords.put("throws","throws"); - keywords.put("case","case"); - keywords.put("enum","enum"); - keywords.put("instanceof","instanceof"); - keywords.put("return","return"); - keywords.put("transient","transient"); - keywords.put("catch","catch"); - keywords.put("extends","extends"); - keywords.put("int","int"); - keywords.put("short","short"); - keywords.put("try","try"); - keywords.put("char","char"); - keywords.put("final","final"); - keywords.put("interface","interface"); - keywords.put("static","static"); - keywords.put("void","void"); - keywords.put("class","class"); - keywords.put("finally","finally"); - keywords.put("long","long"); - keywords.put("strictfp","strictfp"); - keywords.put("volatile","volatile"); - keywords.put("const","const"); - keywords.put("float","float"); - keywords.put("native ","native "); - keywords.put("super","super"); - keywords.put("while","while"); - keywords.put("goto","goto"); - } - - @Override - public String getLanguageIdentifier() { - return "java"; - } - - @Override - public Collection getReservedKeywords() { - return keywords.values(); - } - - @Override - public boolean isReservedKeyword(String keyword) { - // TODO Auto-generated method stub - return keywords.containsKey(keyword); - } - - @Override - public String convertSimplNameToLanguageName(String simplName) - throws SIMPLTranslationException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String convertLanguageNameToSimplName(String lanugageName) - throws SIMPLTranslationException { - // TODO Auto-generated method stub - return null; - } - -} +package ecologylab.serialization; + +import java.util.Collection; +import java.util.HashMap; + +public class JavaLanguage implements ISimplLanguage{ + + private static HashMap keywords = new HashMap(); + + static + { + keywords.put("abstract", "abstract"); + keywords.put("continue","continue"); + keywords.put("for","for"); + keywords.put("new","new"); + keywords.put("switch","switch"); + keywords.put("assert","assert"); + keywords.put("default","default"); + keywords.put("package","package"); + keywords.put("synchronized","synchronized"); + keywords.put("boolean","boolean"); + keywords.put("do","do"); + keywords.put("if","if"); + keywords.put("private","private"); + keywords.put("this","this"); + keywords.put("break","break"); + keywords.put("double","double"); + keywords.put("implements","implements"); + keywords.put("protected","protected"); + keywords.put("throw","throw"); + keywords.put("byte","byte"); + keywords.put("else","else"); + keywords.put("import","import"); + keywords.put("public","public"); + keywords.put("throws","throws"); + keywords.put("case","case"); + keywords.put("enum","enum"); + keywords.put("instanceof","instanceof"); + keywords.put("return","return"); + keywords.put("transient","transient"); + keywords.put("catch","catch"); + keywords.put("extends","extends"); + keywords.put("int","int"); + keywords.put("short","short"); + keywords.put("try","try"); + keywords.put("char","char"); + keywords.put("final","final"); + keywords.put("interface","interface"); + keywords.put("static","static"); + keywords.put("void","void"); + keywords.put("class","class"); + keywords.put("finally","finally"); + keywords.put("long","long"); + keywords.put("strictfp","strictfp"); + keywords.put("volatile","volatile"); + keywords.put("const","const"); + keywords.put("float","float"); + keywords.put("native ","native "); + keywords.put("super","super"); + keywords.put("while","while"); + keywords.put("goto","goto"); + } + + @Override + public String getLanguageIdentifier() { + return "java"; + } + + @Override + public Collection getReservedKeywords() { + return keywords.values(); + } + + @Override + public boolean isReservedKeyword(String keyword) { + // TODO Auto-generated method stub + return keywords.containsKey(keyword); + } + + @Override + public String convertSimplNameToLanguageName(String simplName) + throws SIMPLTranslationException { + // TODO Auto-generated method stub + return null; + } + + @Override + public String convertLanguageNameToSimplName(String lanugageName) + throws SIMPLTranslationException { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/simplCore/src/ecologylab/serialization/Makefile b/simplCore/src/ecologylab/serialization/Makefile index c38345b6..b7d6bf5d 100644 --- a/simplCore/src/ecologylab/serialization/Makefile +++ b/simplCore/src/ecologylab/serialization/Makefile @@ -1,17 +1,17 @@ -# current working directory -DIR = ecologylab/xml - -JAVA_SRC = CharacterConstants.java IO.java XmlTranslationException.java \ - NameSpace.java XmlTools.java ElementState.java - -JAVA_ROOT= ../../ - -MAKE_DIR = ../../../../makefiles -include $(MAKE_DIR)/applets.make - -cabsign: all - -nsjar: all - -sunjar: all - +# current working directory +DIR = ecologylab/xml + +JAVA_SRC = CharacterConstants.java IO.java XmlTranslationException.java \ + NameSpace.java XmlTools.java ElementState.java + +JAVA_ROOT= ../../ + +MAKE_DIR = ../../../../makefiles +include $(MAKE_DIR)/applets.make + +cabsign: all + +nsjar: all + +sunjar: all + diff --git a/simplCore/src/ecologylab/serialization/NameSpaceDecl.java b/simplCore/src/ecologylab/serialization/NameSpaceDecl.java index 0ecdfc99..d29b36f1 100644 --- a/simplCore/src/ecologylab/serialization/NameSpaceDecl.java +++ b/simplCore/src/ecologylab/serialization/NameSpaceDecl.java @@ -1,29 +1,29 @@ -/** - * - */ -package ecologylab.serialization; - -import ecologylab.generic.Debug; - -/** - * Declare an XML Namespace, by mapping a URI String to an ElementState subclass. - * - * @author andruid - */ -public class NameSpaceDecl extends Debug -{ - final String urn; - final Class esClass; - final SimplTypesScope translationScope; - - /** - * - */ - public NameSpaceDecl(String urn, Class esClass, SimplTypesScope translationScope) - { - this.urn = urn; - this.esClass = esClass; - this.translationScope = translationScope; - } - -} +/** + * + */ +package ecologylab.serialization; + +import ecologylab.generic.Debug; + +/** + * Declare an XML Namespace, by mapping a URI String to an ElementState subclass. + * + * @author andruid + */ +public class NameSpaceDecl extends Debug +{ + final String urn; + final Class esClass; + final SimplTypesScope translationScope; + + /** + * + */ + public NameSpaceDecl(String urn, Class esClass, SimplTypesScope translationScope) + { + this.urn = urn; + this.esClass = esClass; + this.translationScope = translationScope; + } + +} diff --git a/simplCore/src/ecologylab/serialization/ObjectiveCLanguage.java b/simplCore/src/ecologylab/serialization/ObjectiveCLanguage.java index 3d71b928..a6e77a2b 100644 --- a/simplCore/src/ecologylab/serialization/ObjectiveCLanguage.java +++ b/simplCore/src/ecologylab/serialization/ObjectiveCLanguage.java @@ -1,39 +1,39 @@ -package ecologylab.serialization; - -import java.util.Collection; - -public class ObjectiveCLanguage implements ISimplLanguage{ - - @Override - public String getLanguageIdentifier() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Collection getReservedKeywords() { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean isReservedKeyword(String keyword) { - // TODO Auto-generated method stub - return false; - } - - @Override - public String convertSimplNameToLanguageName(String simplName) - throws SIMPLTranslationException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String convertLanguageNameToSimplName(String lanugageName) - throws SIMPLTranslationException { - // TODO Auto-generated method stub - return null; - } - -} +package ecologylab.serialization; + +import java.util.Collection; + +public class ObjectiveCLanguage implements ISimplLanguage{ + + @Override + public String getLanguageIdentifier() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection getReservedKeywords() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isReservedKeyword(String keyword) { + // TODO Auto-generated method stub + return false; + } + + @Override + public String convertSimplNameToLanguageName(String simplName) + throws SIMPLTranslationException { + // TODO Auto-generated method stub + return null; + } + + @Override + public String convertLanguageNameToSimplName(String lanugageName) + throws SIMPLTranslationException { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/simplCore/src/ecologylab/serialization/PythonLanguage.java b/simplCore/src/ecologylab/serialization/PythonLanguage.java index f9a5acf9..74f74787 100644 --- a/simplCore/src/ecologylab/serialization/PythonLanguage.java +++ b/simplCore/src/ecologylab/serialization/PythonLanguage.java @@ -1,39 +1,39 @@ -package ecologylab.serialization; - -import java.util.Collection; - -public class PythonLanguage implements ISimplLanguage{ - - @Override - public String getLanguageIdentifier() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Collection getReservedKeywords() { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean isReservedKeyword(String keyword) { - // TODO Auto-generated method stub - return false; - } - - @Override - public String convertSimplNameToLanguageName(String simplName) - throws SIMPLTranslationException { - // TODO Auto-generated method stub - return null; - } - - @Override - public String convertLanguageNameToSimplName(String lanugageName) - throws SIMPLTranslationException { - // TODO Auto-generated method stub - return null; - } - -} +package ecologylab.serialization; + +import java.util.Collection; + +public class PythonLanguage implements ISimplLanguage{ + + @Override + public String getLanguageIdentifier() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection getReservedKeywords() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isReservedKeyword(String keyword) { + // TODO Auto-generated method stub + return false; + } + + @Override + public String convertSimplNameToLanguageName(String simplName) + throws SIMPLTranslationException { + // TODO Auto-generated method stub + return null; + } + + @Override + public String convertLanguageNameToSimplName(String lanugageName) + throws SIMPLTranslationException { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/simplCore/src/ecologylab/serialization/ReflectionTools.java b/simplCore/src/ecologylab/serialization/ReflectionTools.java deleted file mode 100644 index 1ce86a72..00000000 --- a/simplCore/src/ecologylab/serialization/ReflectionTools.java +++ /dev/null @@ -1,14 +0,0 @@ -package ecologylab.serialization; - -import java.util.List; - -public class ReflectionTools { - - public static List GetEnumerationValues(Class ce) - { - - return null; - - - } -} diff --git a/simplCore/src/ecologylab/serialization/SIMPLDescriptionException.java b/simplCore/src/ecologylab/serialization/SIMPLDescriptionException.java index 0b1c177b..dcdab4ce 100644 --- a/simplCore/src/ecologylab/serialization/SIMPLDescriptionException.java +++ b/simplCore/src/ecologylab/serialization/SIMPLDescriptionException.java @@ -1,13 +1,13 @@ -package ecologylab.serialization; - -public class SIMPLDescriptionException extends Exception { - public SIMPLDescriptionException(String s) - { - super(s); - } - - public SIMPLDescriptionException(String s, Throwable t) - { - super(s,t); - } -} +package ecologylab.serialization; + +public class SIMPLDescriptionException extends Exception { + public SIMPLDescriptionException(String s) + { + super(s); + } + + public SIMPLDescriptionException(String s, Throwable t) + { + super(s,t); + } +} diff --git a/simplCore/src/ecologylab/serialization/SIMPLTranslationException.java b/simplCore/src/ecologylab/serialization/SIMPLTranslationException.java index 40caea2c..6c1e3523 100644 --- a/simplCore/src/ecologylab/serialization/SIMPLTranslationException.java +++ b/simplCore/src/ecologylab/serialization/SIMPLTranslationException.java @@ -1,132 +1,132 @@ -package ecologylab.serialization; - -import java.util.List; -import java.util.ArrayList; -import ecologylab.generic.Debug; -import ecologylab.net.ParsedURL; - -/** - * There are certain rules one has to follow while using this framework for - * translation from Java to XML and back. This exception class enforces those - * rules on the user. So, if the user fails to follow any of the rule, this - * exception is thrown with appropriate error message encapsulated in it. This - * exception is thrown in the following conditions: - *

    - *
  • If the user is translating a class which has some Collection type object - * in it (e.g Vector, Hashtable)and the class does not overrides the methods - * getCollection() and addElement() inherited from - * ElementState.
  • - *
  • If the user is translating a class which has some Collection type object - * in it and the collection does not contain items of objects derived from - * ElementState type.
  • - *
  • The classes to be translated does not provide a constructor with zero - * arguments. In this case the exception is thrown only when the user is - * building Java classes from xml.
  • - *
  • The class to be translated does not provide setter method for setting - * the values of the primitive type variables which are translated. In this case - * the exception is thrown only when the user is building Java classes from xml. - *
  • - *
- * - * @author Andruid Kerne - * @author Madhur Khandelwal - * @version 0.5 - */ - -public class SIMPLTranslationException extends Exception implements - XMLTranslationExceptionTypes -{ - private static final long serialVersionUID = -8326348358064487418L; - - private int exceptionType = 0; - - private ArrayList simplIssues; - - private ArrayList childExceptions; - - public SIMPLTranslationException() - { - super(); - this.simplIssues = new ArrayList(); - this.childExceptions = new ArrayList(); - } - - public SIMPLTranslationException(SimplIssue si) - { - this(); - this.simplIssues.add(si); - } - - - public SIMPLTranslationException(String msg) - { - super(msg); - - this.simplIssues = new ArrayList(); - childExceptions = new ArrayList(); - } - - public SIMPLTranslationException(String msg, Exception e) - { - super("XmlTranslationException\n" + msg + "\n\tThe error is " - + e.toString() + " in" + "\n\t" + e.getStackTrace()[0] + "\n\t" - + e.getStackTrace()[1] + "\n\t" + e.getStackTrace()[2] + "\n\t" - + e.getStackTrace()[3] + "\n\t"); - } - - public SIMPLTranslationException(int exceptionType) - { - super(); - - this.exceptionType = exceptionType; - } - - public SIMPLTranslationException(String msg, int exceptionType) - { - this(msg); - - this.exceptionType = exceptionType; - } - - public SIMPLTranslationException(String msg, Exception e, int exceptionType) - { - this(msg, e); - - this.exceptionType = exceptionType; - } - - /** - * Returns the type of exception that generated the XmlTranslationException. - * These can be referenced from the interface XmlTranslationExceptionTypes. - * - * @return - */ - public int getExceptionType() - { - return exceptionType; - } - - public void printTraceOrMessage(Debug that, String msg, ParsedURL purl) - { - switch (getExceptionType()) - { - case FILE_NOT_FOUND: - String purlMsg = (purl == null) ? "" : purl.toString(); - that.warning("File not found - " + msg + " - "+purlMsg); - break; - case NULL_PURL: - Debug.weird(that, "\tCan't open " + msg + " - ParsedURL is null"); - break; - default: - this.printStackTrace(); - break; - } - } - - public Object remnant; - public void setRemnantObject(Object result) { - // TODO Auto-generated method stub - this.remnant = result; - } - -} +package ecologylab.serialization; + +import java.util.List; +import java.util.ArrayList; +import ecologylab.generic.Debug; +import ecologylab.net.ParsedURL; + +/** + * There are certain rules one has to follow while using this framework for + * translation from Java to XML and back. This exception class enforces those + * rules on the user. So, if the user fails to follow any of the rule, this + * exception is thrown with appropriate error message encapsulated in it. This + * exception is thrown in the following conditions: + *
    + *
  • If the user is translating a class which has some Collection type object + * in it (e.g Vector, Hashtable)and the class does not overrides the methods + * getCollection() and addElement() inherited from + * ElementState.
  • + *
  • If the user is translating a class which has some Collection type object + * in it and the collection does not contain items of objects derived from + * ElementState type.
  • + *
  • The classes to be translated does not provide a constructor with zero + * arguments. In this case the exception is thrown only when the user is + * building Java classes from xml.
  • + *
  • The class to be translated does not provide setter method for setting + * the values of the primitive type variables which are translated. In this case + * the exception is thrown only when the user is building Java classes from xml. + *
  • + *
+ * + * @author Andruid Kerne + * @author Madhur Khandelwal + * @version 0.5 + */ + +public class SIMPLTranslationException extends Exception implements + XMLTranslationExceptionTypes +{ + private static final long serialVersionUID = -8326348358064487418L; + + private int exceptionType = 0; + + private ArrayList simplIssues; + + private ArrayList childExceptions; + + public SIMPLTranslationException() + { + super(); + this.simplIssues = new ArrayList(); + this.childExceptions = new ArrayList(); + } + + public SIMPLTranslationException(SimplIssue si) + { + this(); + this.simplIssues.add(si); + } + + + public SIMPLTranslationException(String msg) + { + super(msg); + + this.simplIssues = new ArrayList(); + childExceptions = new ArrayList(); + } + + public SIMPLTranslationException(String msg, Exception e) + { + super("XmlTranslationException\n" + msg + "\n\tThe error is " + + e.toString() + " in" + "\n\t" + e.getStackTrace()[0] + "\n\t" + + e.getStackTrace()[1] + "\n\t" + e.getStackTrace()[2] + "\n\t" + + e.getStackTrace()[3] + "\n\t"); + } + + public SIMPLTranslationException(int exceptionType) + { + super(); + + this.exceptionType = exceptionType; + } + + public SIMPLTranslationException(String msg, int exceptionType) + { + this(msg); + + this.exceptionType = exceptionType; + } + + public SIMPLTranslationException(String msg, Exception e, int exceptionType) + { + this(msg, e); + + this.exceptionType = exceptionType; + } + + /** + * Returns the type of exception that generated the XmlTranslationException. + * These can be referenced from the interface XmlTranslationExceptionTypes. + * + * @return + */ + public int getExceptionType() + { + return exceptionType; + } + + public void printTraceOrMessage(Debug that, String msg, ParsedURL purl) + { + switch (getExceptionType()) + { + case FILE_NOT_FOUND: + String purlMsg = (purl == null) ? "" : purl.toString(); + that.warning("File not found - " + msg + " - "+purlMsg); + break; + case NULL_PURL: + Debug.weird(that, "\tCan't open " + msg + " - ParsedURL is null"); + break; + default: + this.printStackTrace(); + break; + } + } + + public Object remnant; + public void setRemnantObject(Object result) { + // TODO Auto-generated method stub + this.remnant = result; + } + +} diff --git a/simplCore/src/ecologylab/serialization/SaverState.java b/simplCore/src/ecologylab/serialization/SaverState.java index e807120c..3f9581a3 100644 --- a/simplCore/src/ecologylab/serialization/SaverState.java +++ b/simplCore/src/ecologylab/serialization/SaverState.java @@ -1,148 +1,148 @@ -/** - * - */ -package ecologylab.serialization; - -import java.io.File; - -import ecologylab.oodss.exceptions.SaveFailedException; -import ecologylab.serialization.formatenums.Format; - -/** - * This class is configured with a file path that serves as its backing store and provides a save() - * method. Invoking the save method will cause this object to write itself to the file. - * - * Provides a field for backingFilePath, which is automatically translated to an absolute path. - * - * Overrides translateFrom to automatically set its backing file. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class SaverState extends ElementState -{ - protected static final String XML_FILE_SUFFIX = ".xml"; - - /** - * Translate a file from XML to a strongly typed tree of XML objects. - * - * Use SAX or DOM parsing depending on the value of useDOMForTranslateTo. - * - * @param xmlFile - * XML source material. - * @param translationScope - * Specifies mapping from XML nodes (elements and attributes) to Java types. - * - * @return Strongly typed tree of ElementState objects. - * @throws SIMPLTranslationException - */ - public static SaverState translateFromXML(File xmlFile, SimplTypesScope translationScope) - throws SIMPLTranslationException - { - SaverState saverState = (SaverState) translationScope.deserialize(xmlFile, Format.XML); - saverState.setBackingFilePath(xmlFile.getAbsolutePath()); - - return saverState; - } - - /** - * Translate a file XML to a strongly typed tree of XML objects. - * - * Use SAX or DOM parsing depending on the value of useDOMForTranslateTo. - * - * @param fileName - * the name of the XML file that needs to be translated. - * @param translationScope - * Specifies mapping from XML nodes (elements and attributes) to Java types. - * - * @return Strongly typed tree of ElementState objects. - * @throws SIMPLTranslationException - */ - public static ElementState translateFromXML(String fileName, SimplTypesScope translationScope) - throws SIMPLTranslationException - { - SaverState saverState = (SaverState) translationScope.deserialize(new File(fileName), - Format.XML); - saverState.setBackingFilePath(fileName); - - return saverState; - } - - /** - * A path to the backing file for this object. If not specified, the call to save() will fail with - * a SaveFailedException. This is specified by providing it in the constructor (for new objects) - * or by calling the SaverState.translateFrom methods. - */ - private String backingFilePath; - - /** Lazily instantiated File for storing this object. */ - private File backingFile; - - /** - * No-argument constructor for XML translation. - */ - public SaverState() - { - super(); - } - - public SaverState(String backingFilePath) - { - this.setBackingFilePath(backingFilePath); - } - - public synchronized void save() throws SaveFailedException - { - if (this.backingFilePath == null) - throw new SaveFailedException("Backing file path not set. Could not save."); - - try - { - SimplTypesScope.serialize(this, this.backingFile(), Format.XML); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - throw new SaveFailedException("Could not write SaverState to file system.", e); - } - } - - /** - * @return the backingFilePath - */ - public String getBackingFilePath() - { - return backingFilePath; - } - - /** - * @param backingFilePath - * the backingFilePath to set - */ - public void setBackingFilePath(String backingFilePath) - { - this.backingFile = null; - this.backingFilePath = backingFilePath; - } - - /** - * Called when saving to get the file to save to. Can be overridden to provide a specific file, if - * desired. - * - * @return - */ - protected File backingFile() - { - if (backingFile == null) - { - synchronized (this) - { - if (backingFile == null) - { - this.backingFile = new File(getBackingFilePath()); - } - } - } - - return this.backingFile; - } -} +/** + * + */ +package ecologylab.serialization; + +import java.io.File; + +import ecologylab.oodss.exceptions.SaveFailedException; +import ecologylab.serialization.formatenums.Format; + +/** + * This class is configured with a file path that serves as its backing store and provides a save() + * method. Invoking the save method will cause this object to write itself to the file. + * + * Provides a field for backingFilePath, which is automatically translated to an absolute path. + * + * Overrides translateFrom to automatically set its backing file. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class SaverState extends ElementState +{ + protected static final String XML_FILE_SUFFIX = ".xml"; + + /** + * Translate a file from XML to a strongly typed tree of XML objects. + * + * Use SAX or DOM parsing depending on the value of useDOMForTranslateTo. + * + * @param xmlFile + * XML source material. + * @param translationScope + * Specifies mapping from XML nodes (elements and attributes) to Java types. + * + * @return Strongly typed tree of ElementState objects. + * @throws SIMPLTranslationException + */ + public static SaverState translateFromXML(File xmlFile, SimplTypesScope translationScope) + throws SIMPLTranslationException + { + SaverState saverState = (SaverState) translationScope.deserialize(xmlFile, Format.XML); + saverState.setBackingFilePath(xmlFile.getAbsolutePath()); + + return saverState; + } + + /** + * Translate a file XML to a strongly typed tree of XML objects. + * + * Use SAX or DOM parsing depending on the value of useDOMForTranslateTo. + * + * @param fileName + * the name of the XML file that needs to be translated. + * @param translationScope + * Specifies mapping from XML nodes (elements and attributes) to Java types. + * + * @return Strongly typed tree of ElementState objects. + * @throws SIMPLTranslationException + */ + public static ElementState translateFromXML(String fileName, SimplTypesScope translationScope) + throws SIMPLTranslationException + { + SaverState saverState = (SaverState) translationScope.deserialize(new File(fileName), + Format.XML); + saverState.setBackingFilePath(fileName); + + return saverState; + } + + /** + * A path to the backing file for this object. If not specified, the call to save() will fail with + * a SaveFailedException. This is specified by providing it in the constructor (for new objects) + * or by calling the SaverState.translateFrom methods. + */ + private String backingFilePath; + + /** Lazily instantiated File for storing this object. */ + private File backingFile; + + /** + * No-argument constructor for XML translation. + */ + public SaverState() + { + super(); + } + + public SaverState(String backingFilePath) + { + this.setBackingFilePath(backingFilePath); + } + + public synchronized void save() throws SaveFailedException + { + if (this.backingFilePath == null) + throw new SaveFailedException("Backing file path not set. Could not save."); + + try + { + SimplTypesScope.serialize(this, this.backingFile(), Format.XML); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + throw new SaveFailedException("Could not write SaverState to file system.", e); + } + } + + /** + * @return the backingFilePath + */ + public String getBackingFilePath() + { + return backingFilePath; + } + + /** + * @param backingFilePath + * the backingFilePath to set + */ + public void setBackingFilePath(String backingFilePath) + { + this.backingFile = null; + this.backingFilePath = backingFilePath; + } + + /** + * Called when saving to get the file to save to. Can be overridden to provide a specific file, if + * desired. + * + * @return + */ + protected File backingFile() + { + if (backingFile == null) + { + synchronized (this) + { + if (backingFile == null) + { + this.backingFile = new File(getBackingFilePath()); + } + } + } + + return this.backingFile; + } +} diff --git a/simplCore/src/ecologylab/serialization/SimplIssue.java b/simplCore/src/ecologylab/serialization/SimplIssue.java index af186cc5..c5a44f0d 100644 --- a/simplCore/src/ecologylab/serialization/SimplIssue.java +++ b/simplCore/src/ecologylab/serialization/SimplIssue.java @@ -1,41 +1,41 @@ -package ecologylab.serialization; - -/** - * A more friendly representation of any "issues" that may occur while simple de/serializing data. - */ -public class SimplIssue { - - /** - * A concise explanation of an error that caused an issue with SIMPL. - */ - public String errorExplanation; - /** - * The problematic string which caused a given issue - */ - public String problematicString; - /** - * The problematic object which cased a given issue. - */ - public Object problematicObject; - - public Exception exception; - - /** - * Creates an instance of simpl issue to describe an issue that occurred in simpl de/serialization - * @param explanation A nice explanation of the issue. For example: "Invalid format for Date" - * @param problemString The string that may have caused the issue. Empty if no string. Example: "132/41/23rg" => A malformatted date. - * @param problemObject The object that may have caused the issue. Null if no object. - */ - public SimplIssue(String explanation, String problemString, Object problemObject) - { - this.errorExplanation = explanation; - this.problematicString = problemString; - this.problematicObject = problemObject; - } - - public SimplIssue exception(Exception ex) { - this.exception = ex; - return this; - } - -} +package ecologylab.serialization; + +/** + * A more friendly representation of any "issues" that may occur while simple de/serializing data. + */ +public class SimplIssue { + + /** + * A concise explanation of an error that caused an issue with SIMPL. + */ + public String errorExplanation; + /** + * The problematic string which caused a given issue + */ + public String problematicString; + /** + * The problematic object which cased a given issue. + */ + public Object problematicObject; + + public Exception exception; + + /** + * Creates an instance of simpl issue to describe an issue that occurred in simpl de/serialization + * @param explanation A nice explanation of the issue. For example: "Invalid format for Date" + * @param problemString The string that may have caused the issue. Empty if no string. Example: "132/41/23rg" => A malformatted date. + * @param problemObject The object that may have caused the issue. Null if no object. + */ + public SimplIssue(String explanation, String problemString, Object problemObject) + { + this.errorExplanation = explanation; + this.problematicString = problemString; + this.problematicObject = problemObject; + } + + public SimplIssue exception(Exception ex) { + this.exception = ex; + return this; + } + +} diff --git a/simplCore/src/ecologylab/serialization/SimplTypesScope.java b/simplCore/src/ecologylab/serialization/SimplTypesScope.java index d7a6679c..d214d7d5 100644 --- a/simplCore/src/ecologylab/serialization/SimplTypesScope.java +++ b/simplCore/src/ecologylab/serialization/SimplTypesScope.java @@ -1,1977 +1,1990 @@ -package ecologylab.serialization; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.annotation.Annotation; -import java.net.URL; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; - -import ecologylab.collections.Scope; -import ecologylab.generic.HashMapArrayList; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.annotations.simpl_map; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.deserializers.pullhandlers.PullDeserializer; -import ecologylab.serialization.deserializers.pullhandlers.binaryformats.BinaryPullDeserializer; -import ecologylab.serialization.deserializers.pullhandlers.stringformats.StringPullDeserializer; -import ecologylab.serialization.formatenums.BinaryFormat; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; -import ecologylab.serialization.serializers.FormatSerializer; -import ecologylab.serialization.serializers.stringformats.StringSerializer; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.TypeRegistry; - -/** - * A set of bindings between XML element names (tags) and associated simple (without package) class - * names, and associated Java ElementState classes. Inheritance is supported. - */ -public final class SimplTypesScope extends ElementState -{ - /* - * Cyclic graph handling fields, switches and maps - */ - public enum GRAPH_SWITCH - { - ON, OFF - } - - public static GRAPH_SWITCH graphSwitch = GRAPH_SWITCH.OFF; - - @simpl_scalar - private String name; - - private SimplTypesScope[] inheritedTypesScopes; - - /** - * Fundamentally, a SimplTypesScope consists of a set of class simple names. These are mapped to - * tag names (camel case conversion), and to Class objects. Because there are many packages, - * globally, there could be more than one class with one single name. - *

- * Among other things, a SimplTypesScope tells us *which* package's version will be used, if - * there are multiple possibilities. This is the case when internal and external versions of a - * message and its constituents are defined for a messaging API. - */ - private Scope> entriesByClassSimpleName = new Scope>(); - - private Scope> entriesByClassName = new Scope>(); - - @simpl_nowrap - @simpl_map("class_descriptor") - private Scope> entriesByTag = new Scope>(); - - private HashMap> entriesByTLVId = new HashMap>(); - - private Scope> entriesByBibTeXType = new Scope>(); - - private final Scope> nameSpaceClassesByURN = new Scope>(); - - /** - * Scope containing all enumerations by their cross platform name - */ - private Scope enumerationsBySimpleName = new Scope(); - - /** - * Scope containing all enumerations by their tag name - */ - @simpl_nowrap - @simpl_map("enumeration_descriptor") - private Scope enumerationsByTag = new Scope(); - - private static HashMap allTypesScopes = new HashMap(); - - /** - * SimplTypesScope has some global static "AllTypesScopes" scopes which can - * interfere with idempotent execution of tests. - * Run this method to reset the global scope before running test code to give you a clean slate. - */ - public static void ResetAllTypesScopes() - { - System.out.println("----------- RESETTING -----------"); - SimplTypesScope.allTypesScopes = new HashMap(); - } - - public static final String STATE = "State"; - - private boolean performFilters; - - static - { - TypeRegistry.init(); - } - - /** - * Default constructor only for use by translateFromXML(). - */ - public SimplTypesScope() - { - - } - - /** - * Building block called by other constructors for most basic name registration functionality. - * - * @param name - */ - private SimplTypesScope(String name) - { - this.name = name; - addSimplTypesScope(name); - } - - /** - * Create a new SimplTypesScope that defines how to translate xml tag names into class names of - * subclasses of ElementState. Begin by copying in the translations from another, pre-existing - * "base" SimplTypesScope. - * - * @param name - * @param inheritedSimplTypesScope - */ - private SimplTypesScope(String name, SimplTypesScope inheritedSimplTypesScope) - { - this(name); - addTranslations(inheritedSimplTypesScope); - SimplTypesScope[] inheritedSimplTypesScopes = new SimplTypesScope[1]; - inheritedSimplTypesScopes[0] = inheritedSimplTypesScope; - this.inheritedTypesScopes = inheritedSimplTypesScopes; - } - - private SimplTypesScope(String name, SimplTypesScope inheritedSimplTypesScope, - Class translation) - { - this(name, inheritedSimplTypesScope); - addTranslation(translation); - addSimplTypesScope(name); - } - - /** - * Create a new SimplTypesScope that defines how to translate xml tag names into class names of - * subclasses of ElementState. Begin by creating the inherited SimplTypesScope ad then adding the - * new ClassDescriptor intothat - * - * @param name - * @param inheritedSimplTypesScope - * @param translation - */ - private SimplTypesScope(String name, SimplTypesScope inheritedSimplTypesScope, - ClassDescriptor translation) - { - this(name, inheritedSimplTypesScope); - addTranslation(translation); - addSimplTypesScope(name); - } - - /** - * Create a new SimplTypesScope that defines how to translate xml tag names into class names of - * subclasses of ElementState. Begin by copying in the translations from another, pre-existing - * "base" SimplTypesScope. - * - * @param name - * @param baseTranslationSet - */ - private SimplTypesScope(String name, SimplTypesScope... inheritedSimplTypesScopes) - { - this(name); - - if (inheritedSimplTypesScopes != null) - { - this.inheritedTypesScopes = inheritedSimplTypesScopes; - int n = inheritedSimplTypesScopes.length; - for (int i = 0; i < n; i++) - addTranslations(inheritedSimplTypesScopes[i]); - } - } - - /** - * Create a new SimplTypesScope that defines how to translate xml tag names into class names of - * subclasses of ElementState. Begin by copying in the translations from another, pre-existing - * "base" SimplTypesScope. - * - * @param name - * @param baseTranslationSet - */ - private SimplTypesScope(String name, Collection baseTranslationsSet) - { - this(name); - for (SimplTypesScope thatSimplTypesScope : baseTranslationsSet) - addTranslations(thatSimplTypesScope); - inheritedTypesScopes = (SimplTypesScope[]) baseTranslationsSet.toArray(); - } - - /** - * Create a new SimplTypesScope that defines how to translate xml tag names into class names of - * subclasses of ElementState. - * - * Set a new default package, and a set of defined translations. - * - * @param name - * Name of the TranslationSpace to be A key for use in the TranslationSpace registry. - * @param translations - * Set of initially defined translations for this. - * @param defaultPackgeName - */ - private SimplTypesScope(String name, Class... translations) - { - this(name, (SimplTypesScope[]) null, translations); - addSimplTypesScope(name); - } - - /** - * Create a new SimplTypesScope that defines how to translate xml tag names into class names of - * subclasses of ElementState. - * - * Set a new default package, and a set of defined translations. - * - * @param name - * Name of the TranslationSpace to be A key for use in the TranslationSpace registry. - * @param translation - * Set of initially defined translations for this. - */ - private SimplTypesScope(String name, ClassDescriptor... translation) - { - this(name, (SimplTypesScope[]) null, translation); - addSimplTypesScope(name); - } - - /** - * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add - * the array of translations, then, make the defaultPackageName available. - * - * @param name - * @param inheritedSimplTypesScopes - * @param translations - */ - private SimplTypesScope(String name, SimplTypesScope[] inheritedSimplTypesScopes, - Class[]... translations) - { - this(name, inheritedSimplTypesScopes); - addTranslations(translations); - } - - /** - * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add - * the array of translations, then, make the defaultPackageName available. - * - * @param name - * @param inheritedSimplTypesScopes - * @param translations - */ - private SimplTypesScope(String name, SimplTypesScope[] inheritedSimplTypesScopes, - ClassDescriptor[]... translations) - { - this(name, inheritedSimplTypesScopes); - addTranslations(translations); - } - - /** - * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add - * the array of translations, then, make the defaultPackageName available. - * - * @param name - * @param translations - * @param baseTranslations - */ - private SimplTypesScope(String name, Collection inheritedTranslationsSet, - Class[] translations) - { - this(name, inheritedTranslationsSet); - addTranslations(translations); - - addSimplTypesScope(name); - } - - /** - * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add - * the array of translations, then, make the defaultPackageName available. - * - * @param name - * @param inheritedTranslationsSet - * @param translations - */ - private SimplTypesScope(String name, Collection inheritedTranslationsSet, - ClassDescriptor[] translations) - { - this(name, inheritedTranslationsSet); - addTranslations(translations); - - addSimplTypesScope(name); - } - - /** - * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add - * the array of translations, then, make the defaultPackageName available. - * - * @param name - * @param inheritedSimplTypesScope - * @param translations A set of arrays of classes. - */ - private SimplTypesScope(String name, SimplTypesScope inheritedSimplTypesScope, - Class[]... translations) - { - this(name, inheritedSimplTypesScope); - addTranslations(translations); - - addSimplTypesScope(name); - } - - /** - * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add - * the array of translations, then, make the defaultPackageName available. - * - * @param name - * @param inheritedSimplTypesScope - * @param translations - */ - private SimplTypesScope(String name, SimplTypesScope inheritedSimplTypesScope, - ClassDescriptor[]... translations) - { - this(name, inheritedSimplTypesScope); - addTranslations(translations); - - addSimplTypesScope(name); - } - - /** - * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add - * the array of translations, then, make the defaultPackageName available. Map XML Namespace - * declarations. - * - * @param name - * @param nameSpaceDecls - * @param inheritedSimplTypesScopes - * @param translations - * @param defaultPackgeName - */ - private SimplTypesScope(String name, NameSpaceDecl[] nameSpaceDecls, - SimplTypesScope[] inheritedSimplTypesScopes, Class[] translations) - { - this(name, inheritedSimplTypesScopes, translations); - addNameSpaceDecls(nameSpaceDecls); - - addSimplTypesScope(name); - } - - /** - * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add - * the array of translations, then, make the defaultPackageName available. Map XML Namespace - * declarations. - * - * @param name - * @param nameSpaceDecls - * @param inheritedSimplTypesScopes - * @param translations - */ - private SimplTypesScope(String name, NameSpaceDecl[] nameSpaceDecls, - SimplTypesScope[] inheritedSimplTypesScopes, ClassDescriptor[] translations) - { - this(name, inheritedSimplTypesScopes, translations); - addNameSpaceDecls(nameSpaceDecls); - - addSimplTypesScope(name); - } - - /** - * Map XML Namespace ElementState subclasses to URIs. - * - * @param nameSpaceDecls - */ - private void addNameSpaceDecls(NameSpaceDecl[] nameSpaceDecls) - { - if (nameSpaceDecls != null) - for (NameSpaceDecl nsd : nameSpaceDecls) - { - registerNameSpaceDecl(nsd); - } - } - - /** - * Enter a NameSpaceDecl into nameSpaceClassesByURN. - * - * @param nsd - */ - private void registerNameSpaceDecl(NameSpaceDecl nsd) - { - nameSpaceClassesByURN.put(nsd.urn, nsd.esClass); - } - - /** - * Add translations, where each translation is defined by an actual Class object. We can get both - * the class name and the package name from the Class object. - * - * @param classes - */ - private void addTranslations(Class[]... arrayOfClasses) - { - if (arrayOfClasses != null) - { - int numClasses = arrayOfClasses.length; - - for (int i = 0; i < numClasses; i++) - { - if (arrayOfClasses[i] != null) - { - for (Class thatClass : arrayOfClasses[i]) - { - addTranslation(thatClass); - } - } - } - } - - allTypesScopes.put(name, this); - } - - /** - * Add translations, where each translation is defined by an actual Class object. We can get both - * the class name and the package name from the Class object. - * - * @param arrayOfClasses - */ - private void addTranslations(ClassDescriptor[]... arrayOfClasses) - { - if (arrayOfClasses != null) - { - int numClasses = arrayOfClasses.length; - - for (int i = 0; i < numClasses; i++) - { - if (arrayOfClasses[i] != null) - { - for (ClassDescriptor thatClass : arrayOfClasses[i]) - { - addTranslation(thatClass); - } - } - } - } - - allTypesScopes.put(name, this); - } - - /** - * Utility for composing SimplTypesScopes. Performs composition by value. That is, - * the entries are copied. - * - * Unlike in union(), if there are duplicates, they will override identical entries in this. - * - * @param inheritedTypesScope - */ - private void addTranslations(SimplTypesScope inheritedTypesScope) - { - if (inheritedTypesScope != null) - { - // copy map entries from inherited maps into new maps - updateMapWithValues(inheritedTypesScope.entriesByClassSimpleName, - entriesByClassSimpleName, "classSimpleName"); - updateMapWithValues(inheritedTypesScope.entriesByClassName, entriesByClassName, - "className"); - updateMapWithValues(inheritedTypesScope.entriesByTag, entriesByTag, "tagName"); - - HashMap> inheritedNameSpaceClassesByURN = inheritedTypesScope.nameSpaceClassesByURN; - if (inheritedNameSpaceClassesByURN != null) - { - for (String urn : inheritedNameSpaceClassesByURN.keySet()) - { - nameSpaceClassesByURN.put(urn, inheritedNameSpaceClassesByURN.get(urn)); - } - } - } - } - - /** - * Update the Map with all the entries in the inherited Map. - * - * @param inheritedMap - * @param warn - */ - private void updateMapWithValues( - Map> inheritedMap, - Map> newMap, String warn) - { - // XXX ANDRUID + ZACH -> concurrent modification exception can occur here (for loop) if - // inheritedMap is modified elsewhere - for (String key : inheritedMap.keySet()) - { - ClassDescriptor translationEntry = inheritedMap.get(key); - updateMapWithEntry(newMap, key, translationEntry, warn); - } - } - - /** - * Update the Map with the entry. - * - * @param newMap - * @param key - * @param translationEntry - * Must be non-null. - * @param warn - */ - private void updateMapWithEntry(Map> newMap, - String key, ClassDescriptor translationEntry, String warn) - { - ClassDescriptor existingEntry = newMap.get(key); - - // final boolean entryExists = existingEntry != null; - // final boolean newEntry = existingEntry != translationEntry; - - final boolean entryExists = existingEntry != null; - final boolean newEntry = !entryExists ? true - : existingEntry.getDescribedClass() != translationEntry.getDescribedClass(); - - if (newEntry) - { - if (entryExists) // look out for redundant entries - warning("Overriding " + warn + " " + key + " with " + translationEntry); - - newMap.put(key, translationEntry); - } - // if (entryExists && newEntry) // look out for redundant entries - // warning("Overriding " + warn + " " + key + " with " + translationEntry); - // - // if (/** !entryExists || **/ newEntry) - // newMap.put(key, translationEntry); - } - - /** - * Add a translation table entry for an ElementState derived sub-class. Assumes that the xmlTag - * can be derived automatically from the className, by translating case-based separators to - * "_"-based separators. - * - * @param classObj - * The object for the class. - */ - public void addTranslation(Class classObj) - { - // Enumerated types behave a bit differently. - if(classObj.isEnum()) - { - if(!this.enumerationsBySimpleName.containsKey(classSimpleName(classObj))) - { - EnumerationDescriptor ed; - try - { - // Add if it isnt there already. - ed = EnumerationDescriptor.get(classObj); - } - catch(SIMPLDescriptionException sde) - { - // We need to wrap this to not upset the API, for now. - throw new RuntimeException(sde); - } - - this.enumerationsByTag.put(ed.getTagName(), ed); - this.enumerationsBySimpleName.put(ed.getName(), ed); - - // Don't think we have other tags here, we really just need simple name - // But putting it here just in case. - ArrayList otherTags = ed.otherTags(); - if (otherTags != null) - { - for (String otherTag : otherTags) - { - if ((otherTag != null) && (!otherTag.isEmpty())) - { - enumerationsByTag.put(otherTag, ed); - } - } - } - } - } - else - { - // Add a class! - ClassDescriptor entry = ClassDescriptor.getClassDescriptor(classObj); - String tagName = entry.getTagName(); - - entriesByTag.put(entry.getTagName(), entry); - entriesByClassSimpleName.put(entry.getDescribedClassSimpleName(), entry); - entriesByClassName.put(classObj.getName(), entry); - - entriesByTLVId.put(entry.getTagName().hashCode(), entry); - entriesByBibTeXType.put(entry.getBibtexType(), entry); - - ArrayList otherTags = entry.otherTags(); - if (otherTags != null) - { - for (String otherTag : otherTags) - { - if ((otherTag != null) && (otherTag.length() > 0)) - { - entriesByTag.put(otherTag, entry); - entriesByTLVId.put(otherTag.hashCode(), entry); - } - } - } - } - } - - /** - * Given a shallow translation*, which is effectively a mock object with overridden or removed functionality - * and annotated with @simpl_inherit_parent_tag - * (For example: A translation with the deserializationPostHook implemented as an empty method) - * - * This method will: - * - * 1. Remove the translation class the "shallow translation" is meant to replace - * 2. Add the shallow translation to the type scope. - * - * Currently used for deserialization w/o dealing with file dependencies. - * Could also be used for testing, etc. - * @param classObj The Shallow Translation to use as an override. - */ - public void overrideWithShallowTranslation(Class classObj) - { - removeTranslation(correspondingClassFor(classObj)); - addTranslation(classObj); - } - // * You could even call it a ... Doppelganger, if you wanted to. - - - private Class correspondingClassFor(Class dummyObj) - { - ClassDescriptor entry = ClassDescriptor.getClassDescriptor(dummyObj); - String tagName = entry.getTagName(); - - ClassDescriptor corresp = entriesByTag.get(tagName); - - return corresp != null? corresp.getDescribedClass() : dummyObj; - } - - /** - * Removes a given translation from the Type Scope - * @param classObj The translation to remove. - */ - public void removeTranslation(Class classObj) - { - ClassDescriptor entry = ClassDescriptor.getClassDescriptor(classObj); - - for (SimplTypesScope simplTypesScope : allTypesScopes.values()) - { - simplTypesScope.removeTranslation(entry, classObj.getName()); - } - - this.removeTranslation(entry, classObj.getName()); - } - - private void removeTranslation(ClassDescriptor entry, String className) - { - entriesByTag.remove(entry.getTagName()); - entriesByClassSimpleName.remove(entry.getDescribedClassSimpleName()); - entriesByClassName.remove(className); - - entriesByTLVId.remove(entry.getTagName().hashCode()); - entriesByBibTeXType.remove(entry.getBibtexType()); - - ArrayList otherTags = entry.otherTags(); - if (otherTags != null) - { - for (String otherTag : otherTags) - { - if ((otherTag != null) && (otherTag.length() > 0)) - { - entriesByTag.remove(otherTag); - entriesByTLVId.remove(otherTag.hashCode()); - } - } - } - } - - - /** - * Add a translation table entry for an ElementState derived sub-class. Assumes that the xmlTag - * can be derived automatically from the className, by translating case-based separators to - * "_"-based separators. - * - * @param classObj - * The object for the class. - */ - public void addTranslation(ClassDescriptor classObj) - { - ClassDescriptor entry = classObj; - String tagName = entry.getTagName(); - - entriesByTag.put(entry.getTagName(), entry); - entriesByClassSimpleName.put(entry.getDescribedClassSimpleName(), entry); - entriesByClassName.put(classObj.getName(), entry); - - entriesByTLVId.put(entry.getTagName().hashCode(), entry); - entriesByBibTeXType.put(entry.getBibtexType(), entry); - - ArrayList otherTags = entry.otherTags(); - if (otherTags != null) - for (String otherTag : otherTags) - { - if ((otherTag != null) && (otherTag.length() > 0)) - { - entriesByTag.put(otherTag, entry); - entriesByTLVId.put(otherTag.hashCode(), entry); - } - } - } - - /** - * Look-up a Class object for the xmlTag, using translations in this, and in - * inherited SimplTypesScopes. Will use defaultPackage name here and, recursivley, in inherited - * scopes, as necessary. - * - * @param xmlTag - * XML node name that we're seeking a Class for. - * @return Class object, or null if there is no associated translation. - */ - public Class xmlTagToClass(String xmlTag) - { - ClassDescriptor entry = xmlTagToTranslationEntry(xmlTag); - return entry.isEmpty() ? null : entry.getDescribedClass(); - } - - /** - * Seek the entry associated with the tag. Recurse through inherited SimplTypesScopes, if - * necessary. - * - * @param xmlTag - * @return - */ - private ClassDescriptor xmlTagToTranslationEntry(String xmlTag) - { - return getClassDescriptorByTag(xmlTag); - } - - /** - * Get the Class object associated with this tag, if there is one. Unlike xmlTagToClass, this call - * will not generate a new blank NameEntry. - * - * @param tag - * @return - */ - public Class getClassByTag(String tag) - { - ClassDescriptor entry = getClassDescriptorByTag(tag); - - return (entry == null) ? null : entry.getDescribedClass(); - } - - public ClassDescriptor getClassDescriptorByTag(String tag) - { - return entriesByTag.get(tag); - } - - public ClassDescriptor getClassDescriptorByTlvId(int id) - { - return entriesByTLVId.get(id); - } - - public ClassDescriptor getClassDescriptorByTLVId(int tlvId) - { - return entriesByTLVId.get(tlvId); - } - - public ClassDescriptor getClassDescriptorByBibTeXType(String typeName) - { - return entriesByBibTeXType.get(typeName); - } - - /** - * Get the Class object associated with the provided class name, if there is one. Unlike - * xmlTagToClass, this call will not generate a new blank NameEntry. - * - * @param classSimpleName - * Simple name of the class (no package). - * @return - */ - public Class getClassBySimpleName(String classSimpleName) - { - ClassDescriptor entry = getClassDescriptorBySimpleName(classSimpleName); - return (entry == null) ? null : entry.getDescribedClass(); - } - - public ClassDescriptor getClassDescriptorBySimpleName(String classSimpleName) - { - return entriesByClassSimpleName.get(classSimpleName); - } - - public Class getClassByName(String className) - { - ClassDescriptor entry = entriesByClassName.get(className); - - return (entry == null) ? null : entry.getDescribedClass(); - } - - public ClassDescriptor getClassDescriptorByClassName(String className) - { - return entriesByClassName.get(className); - } - - public ArrayList> getAllClasses() - { - ArrayList> classes = new ArrayList>(); - Collection> classDescriptors = this - .getClassDescriptors(); - - for (SimplTypesScope typesScope : allTypesScopes.values()) - { - for (ClassDescriptor classDescriptor : typesScope.entriesByClassSimpleName - .values()) - { - classes.add(classDescriptor.getDescribedClass()); - } - } - return classes; - } - - /** - * Use this SimplTypesScope to lookup a class that has the same simple name as the argument - * passed in here. It may have a different full name, that is, a different package, which could be - * quite convenient for overriding with subclasses. - * - * @param thatClass - * @return - */ - public Class getClassBySimpleNameOfClass(Class thatClass) - { - return getClassBySimpleName(classSimpleName(thatClass)); - } - - /** - * Lookup the tag for the class in question, using this. - * - * @param thatClass - * @return - */ - public String getTag(Class thatClass) - { - return getTagBySimpleName(classSimpleName(thatClass)); - } - - public String getTagBySimpleName(String simpleName) - { - ClassDescriptor entry = entriesByClassSimpleName.get(simpleName); - - return (entry == null) ? null : entry.getTagName(); - } - - /** - * Derive the XML tag from the Class object, using camel case conversion, or the @simpl_tag - * annotation that may be present in a class declaration. - * - * @param thatClass - * @return - */ - private static String determineXMLTag(Class thatClass) - { - Annotation[] annotations = thatClass.getDeclaredAnnotations(); - for (Annotation annotation : annotations) - { - if (annotation.annotationType().equals(simpl_tag.class)) - { - return simpl_tag.class.cast(annotation).value(); - } - } - return XMLTools.getXmlTagName(thatClass.getSimpleName(), "State"); - } - - private String toStringCache; - - @Override - public String toString() - { - if (toStringCache == null) - { - toStringCache = "SimplTypesScope[" + name + "]"; - } - return toStringCache; - } - - /** - * Find the SimplTypesScope called name, if there is one. - * - * @param name - * @return - */ - public static SimplTypesScope lookup(String name) - { - return allTypesScopes.get(name); - } - - /** - * Unlike other get() methods in this class, this one is not a factory, but a simple accessor. It - * performs a lookup, but does not construct. - * - * @param name - * @return - */ - public static SimplTypesScope get(String name) - { - return lookup(name); - } - - /** - * Find an existing SimplTypesScope by this name, or create a new one. - * - * @param name - * the name of the SimplTypesScope - * @param translations - * a set of Classes to be used as a part of this SimplTypesScope - * @return - */ - public static SimplTypesScope get(String name, Class... translations) - { - SimplTypesScope result = lookup(name); - if (result == null) - { - synchronized (name) - { - result = lookup(name); - if (result == null) - result = new SimplTypesScope(name, translations); - } - } - return result; - } - - /** - * Find an existing SimplTypesScope by this name, or create a new one. Inherit from the previous - * SimplTypesScope, by including all mappings from there. - * - * If new translations are provided when the SimplTypesScope already exists in the static scope - * map, they are ignored. - * - * @param name - * @param inheritedTranslations - * @param translations - * @return - */ - public static SimplTypesScope get(String name, SimplTypesScope inheritedTranslations, - Class[]... translations) - { - SimplTypesScope result = lookup(name); - if (result == null) - { - synchronized (name) - { - result = lookup(name); - if (result == null) - result = new SimplTypesScope(name, inheritedTranslations, translations); - } - } - return result; - } - - /** - * Find an existing SimplTypesScope by this name, or create a new one. Inherit from the previous - * SimplTypesScope, by including all mappings from there. - * - * If new translations are provided when the SimplTypesScope already exists in the static scope - * map, they are ignored. - * - * @param name - * @param inheritedTranslations - * @param translations - * @return - */ - public static SimplTypesScope get(String name, SimplTypesScope inheritedTranslations, - Class... translations) - { - SimplTypesScope result = lookup(name); - if (result == null) - { - synchronized (name) - { - result = lookup(name); - if (result == null) - result = new SimplTypesScope(name, inheritedTranslations, translations); - } - } - return result; - } - - /** - * Find an existing SimplTypesScope by this name, or create a new one. Build on a previous - * SimplTypesScope, by including all mappings from there. Add just a single new class. - * - * @param name - * @param inheritedTranslations - * @param translation - * @return - */ - public static SimplTypesScope get(String name, SimplTypesScope inheritedTranslations, - Class translation) - { - SimplTypesScope result = lookup(name); - if (result == null) - { - synchronized (name) - { - result = lookup(name); - if (result == null) - result = new SimplTypesScope(name, inheritedTranslations, translation); - } - } - return result; - } - - /** - * Find an existing SimplTypesScope by this name, or create a new one. Add just a single new - * class. - * - * @param name - * @param translation - * @return - */ - public static SimplTypesScope get(String name, Class translation) - { - return get(name, null, translation); - } - - /** - * Find an existing SimplTypesScope by this name, or create a new one. Build on the previous - * SimplTypesScope, by including all mappings from there. - * - * @param name - * the name of the SimplTypesScope to acquire. - * @param translations - * an array of translations to add to the scope. - * @param inheritedTranslations - * a list of previous translation scopes to build upon. - * @return - */ - public static SimplTypesScope get(String name, SimplTypesScope[] inheritedTranslationsSet, - Class... translations) - { - SimplTypesScope result = lookup(name); - if (result == null) - { - synchronized (name) - { - result = lookup(name); - if (result == null) - result = new SimplTypesScope(name, inheritedTranslationsSet, translations); - } - } - return result; - } - - /** - * Find an existing SimplTypesScope by this name, or create a new one. Build on the previous - * SimplTypesScope, by including all mappings from there. - * - * @param name - * the name of the SimplTypesScope to acquire. - * @param translations - * an array of translations to add to the scope. - * @param inheritedTranslations - * a list of previous translation scopes to build upon. - * @return - */ - public static SimplTypesScope get(String name, SimplTypesScope[] inheritedTranslationsSet, - Class[]... translations) - { - SimplTypesScope result = lookup(name); - if (result == null) - { - synchronized (name) - { - result = lookup(name); - if (result == null) - result = new SimplTypesScope(name, inheritedTranslationsSet, translations); - } - } - return result; - } - - public static SimplTypesScope get(String name, SimplTypesScope inheritedTranslations0, - SimplTypesScope inheritedTranslations1, Class... translations) - { - SimplTypesScope[] inheritedArray = new SimplTypesScope[2]; - inheritedArray[0] = inheritedTranslations0; - inheritedArray[1] = inheritedTranslations1; - return get(name, inheritedArray, translations); - } - - public static SimplTypesScope get(String name, NameSpaceDecl[] nameSpaceDecls, - Class... translations) - { - return get(name, nameSpaceDecls, null, translations); - } - - /** - * Find an existing SimplTypesScope by this name, or create a new one. Build on a set of - * inherited SimplTypesScopes, by including all mappings from them. - * - * @param name - * @param nameSpaceDecls - * Array of ElementState class + URI key map entries for handling XML Namespaces. - * @param inheritedTranslationsSet - * @param translations - * @param defaultPackageName - * @return - */ - public static SimplTypesScope get(String name, NameSpaceDecl[] nameSpaceDecls, - SimplTypesScope[] inheritedTranslationsSet, Class... translations) - { - SimplTypesScope result = lookup(name); - if (result == null) - { - synchronized (name) - { - result = lookup(name); - if (result == null) - result = new SimplTypesScope(name, nameSpaceDecls, inheritedTranslationsSet, - translations); - } - } - return result; - } - - /** - * Find an existing SimplTypesScope by this name, or create a new one. Build on a set of - * inherited SimplTypesScopes, by including all mappings from them. - * - * @param name - * @param inheritedTranslations - * @return - */ - public static SimplTypesScope get(String name, SimplTypesScope... inheritedTranslations) - { - return get(name, inheritedTranslations, (Class []) null); - } - - /** - * Find an existing SimplTypesScope by this name, or create a new one. Build on a set of - * inherited SimplTypesScopes, by including all mappings from them. - * - * @param name - * @param inheritedTranslationsSet - * @param translations - * @return - */ - public static SimplTypesScope get(String name, - Collection inheritedTranslationsSet, Class... translations) - { - SimplTypesScope result = lookup(name); - if (result == null) - { - synchronized (name) - { - result = lookup(name); - if (result == null) - result = new SimplTypesScope(name, inheritedTranslationsSet, translations); - } - } - return result; - } - - protected HashMap> entriesByClassSimpleName() - { - return entriesByClassSimpleName; - } - - public HashMap> entriesByClassName() - { - return entriesByClassName; - } - - public HashSet addClassNamesToHashSet(HashSet hashSet) - { - if (inheritedTypesScopes != null) - { - for (SimplTypesScope inheritedTScope : inheritedTypesScopes) - { - inheritedTScope.generateImports(hashSet); - } - } - this.generateImports(hashSet); - return hashSet; - } - - protected void generateImports(HashSet hashSet) - { - for (String className : entriesByClassName.keySet()) - { - hashSet.add(className); - } - } - - private ArrayList> classDescriptors; - - // FIXME -- implement this! - public ArrayList> getClassDescriptors() - { - ArrayList> result = classDescriptors; - if (result == null) - { - result = new ArrayList>(entriesByTag.values()); // we use entriesByTag so that overriding works well. - this.classDescriptors = result; - } - return result; - } - - /** - * Get the Scalar Type corresponding to the Class. - * - * @param thatClass - * @return Type associated with thatClass - */ - ScalarType getType(Class thatClass) - { - return TypeRegistry.getScalarType(thatClass); - } - - /** - * Lookup a NameSpace ElementState subclass, with a URN as the key. - * - * @param urn - * @return - */ - public Class lookupNameSpaceByURN(String urn) - { - return nameSpaceClassesByURN.get(urn); - } - - /** - * - * @return The unique name of this. - */ - public String getName() - { - return name; - } - - public static final String BASIC_TRANSLATIONS = "basic_translations"; - - private void addSimplTypesScope(String name) - { - synchronized(allTypesScopes) - { - if(!allTypesScopes.containsKey(name)) - { - // TODO: Concurrency? yo. - allTypesScopes.put(name, this); - }else{ - //throw new RuntimeException("OH NO EVERYTHING IS AMISS FOR: " + name); - } - } - } - - - public Object deserialize(File file, TranslationContext translationContext, - DeserializationHookStrategy deserializationHookStrategy, Format format) - throws SIMPLTranslationException - { - PullDeserializer pullDeserializer = PullDeserializer.getDeserializer(this, translationContext, - deserializationHookStrategy, format); - return pullDeserializer.parse(file); - } - - public Object deserialize(File file, TranslationContext translationContext, Format format) - throws SIMPLTranslationException - { - return deserialize(file, translationContext, null, format); - } - - public Object deserialize(File file, Format format) throws SIMPLTranslationException - { - TranslationContext translationContext= new TranslationContext(); - Object obj = deserialize(file, translationContext, null, format); - return obj; - } - - public Object deserialize(File file, DeserializationHookStrategy deserializationHookStrategy, - Format format) throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - Object obj = deserialize(file, translationContext, deserializationHookStrategy, format); - return obj; - } - - public Object deserialize(ParsedURL parsedURL, - DeserializationHookStrategy deserializationHookStrategy, Format format) - throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - Object obj = deserialize(parsedURL, translationContext, deserializationHookStrategy, format); - return obj; - } - - public Object deserialize(ParsedURL parsedURL, TranslationContext translationContext, - Format format) throws SIMPLTranslationException - { - return deserialize(parsedURL, translationContext, null, format); - } - - public Object deserialize(ParsedURL parsedURL, Format format) throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - Object obj = deserialize(parsedURL, translationContext, null, format); - return obj; - } - - public Object deserialize(ParsedURL parsedURL, TranslationContext translationContext, - DeserializationHookStrategy deserializationHookStrategy, Format format) - throws SIMPLTranslationException - { - PullDeserializer pullDeserializer = PullDeserializer.getDeserializer(this, translationContext, - deserializationHookStrategy, format); - return pullDeserializer.parse(parsedURL); - } - - public Object deserialize(InputStream inputStream, - DeserializationHookStrategy deserializationHookStrategy, Format format) - throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - Object obj = deserialize(inputStream, translationContext, deserializationHookStrategy, format, - null); - return obj; - } - - public Object deserialize(InputStream inputStream, - DeserializationHookStrategy deserializationHookStrategy, Format format, Charset charSet) - throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - Object obj = deserialize(inputStream, translationContext, deserializationHookStrategy, format, - charSet); - return obj; - } - - public Object deserialize(InputStream inputStream, TranslationContext translationContext, - Format format) throws SIMPLTranslationException - { - return deserialize(inputStream, translationContext, null, format, null); - } - - public Object deserialize(InputStream inputStream, TranslationContext translationContext, - Format format, Charset charSet) throws SIMPLTranslationException - { - return deserialize(inputStream, translationContext, null, format, charSet); - } - - public Object deserialize(InputStream inputStream, Format format) - throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - Object obj = deserialize(inputStream, translationContext, null, format, null); - return obj; - } - - public Object deserialize(InputStream inputStream, Format format, Charset charSet) - throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - Object obj = deserialize(inputStream, translationContext, null, format, charSet); - return obj; - } - -public Object deserialize(InputStream inputStream, TranslationContext translationContext, - DeserializationHookStrategy deserializationHookStrategy, Format format, Charset charSet) - throws SIMPLTranslationException -{ - PullDeserializer pullDeserializer = PullDeserializer.getDeserializer(this, translationContext, - deserializationHookStrategy, format); - if(charSet != null) - { - return pullDeserializer.parse(inputStream, charSet); - } - else - { - return pullDeserializer.parse(inputStream); - } -} - - public Object deserialize(URL url, Format format) throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - Object obj = deserialize(new ParsedURL(url), translationContext, null, format); - return obj; - } - - public Object deserialize(CharSequence charSequence, TranslationContext translationContext, - DeserializationHookStrategy deserializationHookStrategy, StringFormat stringFormat) - throws SIMPLTranslationException - { - StringPullDeserializer pullDeserializer = PullDeserializer.getStringDeserializer(this, - translationContext, deserializationHookStrategy, stringFormat); - return pullDeserializer.parse(charSequence); - } - - public Object deserialize(CharSequence charSequence, - DeserializationHookStrategy deserializationHookStrategy, StringFormat stringFormat) - throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - StringPullDeserializer pullDeserializer = PullDeserializer.getStringDeserializer(this, - translationContext, deserializationHookStrategy, stringFormat); - return pullDeserializer.parse(charSequence); - } - - public Object deserialize(CharSequence charSequence, TranslationContext translationContext, - StringFormat stringFormat) throws SIMPLTranslationException - { - return deserialize(charSequence, translationContext, null, stringFormat); - } - - public Object deserialize(CharSequence charSequence, StringFormat stringFormat) - throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - Object obj = deserialize(charSequence, translationContext, null, stringFormat); - return obj; - } - - public Object deserialize(byte[] byteArray, TranslationContext translationContext, - DeserializationHookStrategy deserializationHookStrategy, BinaryFormat binaryFormat) - throws SIMPLTranslationException - { - BinaryPullDeserializer binaryPullDeserializer = PullDeserializer.getBinaryDeserializer(this, - translationContext, deserializationHookStrategy, binaryFormat); - return binaryPullDeserializer.parse(byteArray); - } - - public static SimplTypesScope getBasicTranslations() - { - return get(BASIC_TRANSLATIONS, SimplTypesScope.class, FieldDescriptor.class, - ClassDescriptor.class); - } - - public static SimplTypesScope augmentTranslationScope(SimplTypesScope simplTypesScope) - { - ArrayList> allClasses = simplTypesScope.getAllClasses(); - Collection> augmentedClasses = augmentTranslationScope(allClasses).values(); - - Class[] augmentedClassesArray = augmentedClasses - .toArray(new Class[augmentedClasses.size()]); - - return new SimplTypesScope(simplTypesScope.getName(), augmentedClassesArray); - } - - private static HashMap> augmentTranslationScope(ArrayList> allClasses) - { - HashMap> augmentedClasses = new HashMap>(); - for (Class thatClass : allClasses) - { - augmentSimplTypesScope(thatClass, augmentedClasses); - } - return augmentedClasses; - } - - private static void augmentSimplTypesScope(Class thatClass, - HashMap> augmentedClasses) - { - if (augmentedClasses.put(thatClass.getSimpleName(), thatClass) != null) - return; - - if (thatClass.getSuperclass() != ElementState.class) - { - augmentSimplTypesScope(thatClass.getSuperclass().asSubclass(ElementState.class), - augmentedClasses); - } - - ClassDescriptor thatClassDescriptor = ClassDescriptor - .getClassDescriptor(thatClass); - - HashMapArrayList fieldDescriptors = thatClassDescriptor - .getFieldDescriptorsByFieldName(); - - if (fieldDescriptors.size() > 0) - { - thatClassDescriptor.resolvePolymorphicAnnotations(); - - for (FieldDescriptor fieldDescriptor : fieldDescriptors) - { - if (fieldDescriptor.isNested()) - { - augmentSimplTypesScope(fieldDescriptor.getFieldType().asSubclass(ElementState.class), - augmentedClasses); - } - else - { - if (fieldDescriptor.isCollection() && !fieldDescriptor.isPolymorphic()) - { - ArrayList> genericClasses = XMLTools.getGenericParameters(fieldDescriptor - .getField()); - - for (Class genericClass : genericClasses) - { - if (genericClass != null && ElementState.class.isAssignableFrom(genericClass)) - { - augmentSimplTypesScope(genericClass.asSubclass(ElementState.class), - augmentedClasses); - } - } - } - else if (fieldDescriptor.isPolymorphic()) - { - Collection polymorphDescriptors = fieldDescriptor - .getPolymorphicClassDescriptors(); - - if (polymorphDescriptors != null) - { - for (ClassDescriptor classDescriptor : polymorphDescriptors) - { - augmentSimplTypesScope(classDescriptor.getDescribedClass(), augmentedClasses); - } - } - } - } - } - } - } - - public void augment() - { - Class[] augmentedClassesArray = getClassesArray(this); - - this.addTranslations(augmentedClassesArray); - } - - private static Class[] getClassesArray(SimplTypesScope simplTypesScope) - { - ArrayList> allClasses = simplTypesScope.getAllClasses(); - Collection> augmentedClasses = augmentTranslationScope(allClasses).values(); - - Class[] augmentedClassesArray = augmentedClasses - .toArray(new Class[augmentedClasses.size()]); - return augmentedClassesArray; - } - - /** - * @return the performFilters - */ - public boolean isPerformFilters() - { - return performFilters; - } - - /** - * @param performFilters - * the performFilters to set - */ - public void setPerformFilters(boolean performFilters) - { - this.performFilters = performFilters; - } - - /** - * Augment the given SimplTypesScope and return the augmented one - * - * @param simplTypesScope - * @return - */ - public static SimplTypesScope augmentTranslationScopeWithClassDescriptors( - SimplTypesScope simplTypesScope) - { - Collection> allClassDescriptors = simplTypesScope - .getClassDescriptors(); - - ArrayList> allClasses = simplTypesScope - .getAllClassDescriptors(); - Collection> augmentedClasses = augmentSimplTypesScopeWithClassDescriptors( - allClasses).values(); - - ClassDescriptor[] augmentedClassesArray = augmentedClasses - .toArray(new ClassDescriptor[augmentedClasses.size()]); - - return new SimplTypesScope(simplTypesScope.getName(), augmentedClassesArray); - } - - /** - * augment the given the list of classes - * - * @param allClasses - * @return - */ - private static HashMap> augmentSimplTypesScopeWithClassDescriptors( - ArrayList> allClasses) - { - HashMap> augmentedClasses = new HashMap>(); - for (ClassDescriptor thatClass : allClasses) - { - augmentSimplTypesScope(thatClass, augmentedClasses); - } - return augmentedClasses; - } - - /** - * augment the given ClassDescriptor - * - * @param thatClass - * @param augmentedClasses - */ - private static void augmentSimplTypesScope(ClassDescriptor thatClass, - HashMap> augmentedClasses) - { - if (augmentedClasses.put(thatClass.getDescribedClassSimpleName(), thatClass) != null) - return; - - ClassDescriptor superClass = thatClass.getSuperClass(); - if (superClass != null && !"ElementState".equals(superClass.getDescribedClassSimpleName())) - { - augmentSimplTypesScope(superClass, augmentedClasses); - } - - HashMapArrayList fieldDescriptors = thatClass - .getFieldDescriptorsByFieldName(); - - if (fieldDescriptors.size() > 0) - { - thatClass.resolvePolymorphicAnnotations(); - - for (FieldDescriptor fieldDescriptor : fieldDescriptors) - { - if (fieldDescriptor.isNested()) - { - augmentSimplTypesScope(fieldDescriptor.getElementClassDescriptor(), augmentedClasses); - } - else - { - if (fieldDescriptor.isCollection() && !fieldDescriptor.isPolymorphic()) - { - ArrayList> genericClasses = XMLTools.getGenericParameters(fieldDescriptor - .getField()); - - for (Class genericClass : genericClasses) - { - if (genericClass != null && ElementState.class.isAssignableFrom(genericClass)) - { - augmentSimplTypesScope(ClassDescriptor.getClassDescriptor(genericClass - .asSubclass(ElementState.class)), augmentedClasses); - } - } - } - else if (fieldDescriptor.isPolymorphic()) - { - Collection polymorphDescriptors = fieldDescriptor - .getPolymorphicClassDescriptors(); - - if (polymorphDescriptors != null) - { - for (ClassDescriptor classDescriptor : polymorphDescriptors) - { - augmentSimplTypesScope(classDescriptor, augmentedClasses); - } - } - } - } - } - } - } - - /** - * Method returning all the class descriptors corresponds to all the translation Scopes - * - * @return - */ - public ArrayList> getAllClassDescriptors() - { - ArrayList> classes = new ArrayList>(); - - for (SimplTypesScope simplTypesScope : allTypesScopes.values()) - { - for (ClassDescriptor classDescriptor : simplTypesScope.entriesByTag - .values()) - { - classes.add(classDescriptor); - } - } - return classes; - } - - /** - * Make a new SimplTypesScope from a subset of this, making sure that the class of all entries in - * the subset is either superClassCriterion or a subclass thereof. - * - * @param newName - * Name for new SimplTypesScope. - * @param superClassCriterion - * Super class discriminant for all classes in the subset. - * - * @return New or existing SimplTypesScope with subset of classes in this, based on - * assignableCriterion. - */ - public SimplTypesScope getAssignableSubset(String newName, Class superClassCriterion) - { - SimplTypesScope result = lookup(newName); - if (result == null) - { - synchronized (entriesByClassName) - { - result = lookup(newName); - if (result == null) - { - result = new SimplTypesScope(newName); - addSimplTypesScope(newName); - for (ClassDescriptor classDescriptor : entriesByClassName.values()) - { - Class thatClass = classDescriptor.getDescribedClass(); - if (superClassCriterion.isAssignableFrom(thatClass)) - result.addTranslation(classDescriptor); - } - } - } - } - return result; - } - - /** - * Make a new SimplTypesScope from a subset of this, making sure that the class of all entries in - * never either superClassCriterion or a subclass thereof. - * - * @param newName - * Name for new SimplTypesScope. - * @param superClassCriterion - * Super class discriminant for all classes to remove from the subset. - * - * @return New or existing SimplTypesScope with subset of classes in this, based on - * assignableCriterion. - */ - public SimplTypesScope getSubtractedSubset(String newName, Class superClassCriterion) - { - SimplTypesScope result = lookup(newName); - if (result == null) - { - synchronized (entriesByClassName) - { - result = lookup(newName); - if (result == null) - { - result = new SimplTypesScope(newName); - addSimplTypesScope(newName); - for (ClassDescriptor classDescriptor : entriesByClassName.values()) - { - Class thatClass = classDescriptor.getDescribedClass(); - if (!superClassCriterion.isAssignableFrom(thatClass)) - result.addTranslation(classDescriptor); - } - } - } - } - return result; - } - - /** - * This will switch on the graph serialization - */ - public static void enableGraphSerialization() - { - graphSwitch = GRAPH_SWITCH.ON; - } - - /** - * This will switch on the graph serialization - */ - public static void disableGraphSerialization() - { - graphSwitch = GRAPH_SWITCH.OFF; - } - - /** - * Rebuild structures after serializing only some fields. - */ - @Override - public void deserializationPostHook(TranslationContext translationContext, Object object) - { - for (ClassDescriptor classDescriptor : entriesByTag.values()) - { - entriesByClassName.put(classDescriptor.getName(), classDescriptor); - String simpleName = classDescriptor.getDescribedClassSimpleName(); - entriesByClassSimpleName.put(simpleName, classDescriptor); - } - if (allTypesScopes.containsKey(name)) - warning("REPLACING another SimplTypesScope of the SAME NAME during deserialization!\t" - + name); - allTypesScopes.put(name, this); - } - - /** - * - * @param object - * @param outputStream - * @param bibtex - * @throws SIMPLTranslationException - */ - public static void serialize(Object object, OutputStream outputStream, Format format) throws SIMPLTranslationException - { - FormatSerializer serializer = FormatSerializer.getSerializer(format); - serializer.serialize(object, outputStream); - } - - /** - * - * @param object - * @param outputStream - * @param format - * @param translationContext - * @throws SIMPLTranslationException - */ - public static void serialize(Object object, OutputStream outputStream, Format format, TranslationContext translationContext) throws SIMPLTranslationException - { - FormatSerializer serializer = FormatSerializer.getSerializer(format); - serializer.serialize(object, outputStream, translationContext); - } - - /** - * Static method for serializing an object. accepts translation context which a user can supply to - * pass in additional information for the serialization method to use - * - * @param object - * @param stringBuilder - * @param format - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - public static StringBuilder serialize(Object object, StringFormat stringFormat, - TranslationContext translationContext) throws SIMPLTranslationException - { - StringSerializer stringSerializer = FormatSerializer.getStringSerializer(stringFormat); - return stringSerializer.serialize(object, translationContext); - } - - /** - * Static method for serializing an object. accepts translation context which a user can supply to - * pass in additional information for the serialization method to use - * - * @param object - * @param stringBuilder - * @param format - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - public static void serialize(Object object, StringBuilder stringBuilder, - StringFormat stringFormat, TranslationContext translationContext) - throws SIMPLTranslationException - { - StringSerializer stringSerializer = FormatSerializer.getStringSerializer(stringFormat); - stringSerializer.serialize(object, stringBuilder, translationContext); - } - - /** - * Static method for serializing an object. accepts translation context which a user can supply to - * pass in additional information for the serialization method to use - * - * @param object - * @param appendable - * @param format - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - public static void serialize(Object object, Appendable appendable, StringFormat stringFormat, - TranslationContext translationContext) throws SIMPLTranslationException - { - StringSerializer stringSerializer = FormatSerializer.getStringSerializer(stringFormat); - stringSerializer.serialize(object, appendable, translationContext); - } - - public static void serializeOut(Object object, String message, StringFormat stringFormat) - { - System.out.print(message); - System.out.print(':'); - try - { - serialize(object, System.out, stringFormat); - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - /** - * Static method for serializing an object to the defined format. TranslationContext is - * automatically initialized to handle graphs if enabled - * - * @param object - * @param appendable - * @param format - * @throws SIMPLTranslationException - * @throws IOException - */ - public static void serialize(Object object, Appendable appendable, StringFormat stringFormat) - throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - serialize(object, appendable, stringFormat, translationContext); - } - - /** - * Static method for serializing an object to the defined format. TranslationContext is - * automatically initialized to handle graphs if enabled - * - * @param object - * @param stringBuilder - * @param stringFormat - * @throws SIMPLTranslationException - * @throws IOException - */ - public static StringBuilder serialize(Object object, StringFormat stringFormat) - throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - StringBuilder sb = serialize(object, stringFormat, translationContext); - return sb; - } - - /** - * Static method for serializing an object to the defined format. TranslationContext is - * automatically initialized to handle graphs if enabled - * - * @param object - * @param stringBuilder - * @param stringFormat - * @throws SIMPLTranslationException - * @throws IOException - */ - public static void serialize(Object object, StringBuilder stringBuilder, StringFormat stringFormat) - throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - serialize(object, stringBuilder, stringFormat, translationContext); - } - - /** - * Static method for serializing an object. accepts translation context which a user can supply to - * pass in additional information for the serialization method to use - * - * @param object - * @param appendable - * @param format - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - public static void serialize(Object object, File file, Format format, - TranslationContext translationContext) throws SIMPLTranslationException - { - FormatSerializer formatSerializer = FormatSerializer.getSerializer(format); - formatSerializer.serialize(object, file, translationContext); - } - - /** - * Static method for serializing an object to the defined format. TranslationContext is - * automatically initialized to handle graphs if enabled - * - * @param object - * @param stringBuilder - * @param stringFormat - * @throws SIMPLTranslationException - * @throws IOException - */ - public static void serialize(Object object, File file, Format format) - throws SIMPLTranslationException - { - TranslationContext translationContext = new TranslationContext(); - serialize(object, file, format, translationContext); - } -} +package ecologylab.serialization; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import ecologylab.collections.Scope; +import ecologylab.generic.HashMapArrayList; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.annotations.simpl_map; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.deserializers.pullhandlers.PullDeserializer; +import ecologylab.serialization.deserializers.pullhandlers.binaryformats.BinaryPullDeserializer; +import ecologylab.serialization.deserializers.pullhandlers.stringformats.StringPullDeserializer; +import ecologylab.serialization.formatenums.BinaryFormat; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; +import ecologylab.serialization.serializers.FormatSerializer; +import ecologylab.serialization.serializers.stringformats.StringSerializer; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.TypeRegistry; + +/** + * A set of bindings between XML element names (tags) and associated simple (without package) class + * names, and associated Java ElementState classes. Inheritance is supported. + */ +public final class SimplTypesScope extends ElementState +{ + /* + * Cyclic graph handling fields, switches and maps + */ + public enum GRAPH_SWITCH + { + ON, OFF + } + + public static GRAPH_SWITCH graphSwitch = GRAPH_SWITCH.OFF; + + @simpl_scalar + private String name; + + private SimplTypesScope[] inheritedTypesScopes; + + /** + * Fundamentally, a SimplTypesScope consists of a set of class simple names. These are mapped to + * tag names (camel case conversion), and to Class objects. Because there are many packages, + * globally, there could be more than one class with one single name. + *

+ * Among other things, a SimplTypesScope tells us *which* package's version will be used, if + * there are multiple possibilities. This is the case when internal and external versions of a + * message and its constituents are defined for a messaging API. + */ + private Scope> entriesByClassSimpleName = new Scope>(); + + private Scope> entriesByClassName = new Scope>(); + + @simpl_nowrap + @simpl_map("class_descriptor") + private Scope> entriesByTag = new Scope>(); + + private HashMap> entriesByTLVId = new HashMap>(); + + private Scope> entriesByBibTeXType = new Scope>(); + + private final Scope> nameSpaceClassesByURN = new Scope>(); + + /** + * Scope containing all enumerations by their cross platform name + */ + private Scope enumerationsBySimpleName = new Scope(); + + /** + * Scope containing all enumerations by their tag name + */ + @simpl_nowrap + @simpl_map("enumeration_descriptor") + private Scope enumerationsByTag = new Scope(); + + private static HashMap allTypesScopes = new HashMap(); + + /** + * SimplTypesScope has some global static "AllTypesScopes" scopes which can + * interfere with idempotent execution of tests. + * Run this method to reset the global scope before running test code to give you a clean slate. + */ + public static void ResetAllTypesScopes() + { + System.out.println("----------- RESETTING -----------"); + SimplTypesScope.allTypesScopes = new HashMap(); + } + + public static final String STATE = "State"; + + private boolean performFilters; + + static + { + TypeRegistry.init(); + } + + /** + * Default constructor only for use by translateFromXML(). + */ + public SimplTypesScope() + { + + } + + /** + * Building block called by other constructors for most basic name registration functionality. + * + * @param name + */ + private SimplTypesScope(String name) + { + this.name = name; + addSimplTypesScope(name); + } + + /** + * Create a new SimplTypesScope that defines how to translate xml tag names into class names of + * subclasses of ElementState. Begin by copying in the translations from another, pre-existing + * "base" SimplTypesScope. + * + * @param name + * @param inheritedSimplTypesScope + */ + private SimplTypesScope(String name, SimplTypesScope inheritedSimplTypesScope) + { + this(name); + addTranslations(inheritedSimplTypesScope); + SimplTypesScope[] inheritedSimplTypesScopes = new SimplTypesScope[1]; + inheritedSimplTypesScopes[0] = inheritedSimplTypesScope; + this.inheritedTypesScopes = inheritedSimplTypesScopes; + } + + private SimplTypesScope(String name, SimplTypesScope inheritedSimplTypesScope, + Class translation) + { + this(name, inheritedSimplTypesScope); + addTranslation(translation); + addSimplTypesScope(name); + } + + /** + * Create a new SimplTypesScope that defines how to translate xml tag names into class names of + * subclasses of ElementState. Begin by creating the inherited SimplTypesScope ad then adding the + * new ClassDescriptor intothat + * + * @param name + * @param inheritedSimplTypesScope + * @param translation + */ + private SimplTypesScope(String name, SimplTypesScope inheritedSimplTypesScope, + ClassDescriptor translation) + { + this(name, inheritedSimplTypesScope); + addTranslation(translation); + addSimplTypesScope(name); + } + + /** + * Create a new SimplTypesScope that defines how to translate xml tag names into class names of + * subclasses of ElementState. Begin by copying in the translations from another, pre-existing + * "base" SimplTypesScope. + * + * @param name + * @param baseTranslationSet + */ + private SimplTypesScope(String name, SimplTypesScope... inheritedSimplTypesScopes) + { + this(name); + + if (inheritedSimplTypesScopes != null) + { + this.inheritedTypesScopes = inheritedSimplTypesScopes; + int n = inheritedSimplTypesScopes.length; + for (int i = 0; i < n; i++) + addTranslations(inheritedSimplTypesScopes[i]); + System.out.println(""); + debug("... Finished initializing inherited SimplTypesScopes...\n"); + } + } + + /** + * Create a new SimplTypesScope that defines how to translate xml tag names into class names of + * subclasses of ElementState. Begin by copying in the translations from another, pre-existing + * "base" SimplTypesScope. + * + * @param name + * @param baseTranslationSet + */ + private SimplTypesScope(String name, Collection baseTranslationsSet) + { + this(name); + for (SimplTypesScope thatSimplTypesScope : baseTranslationsSet) + addTranslations(thatSimplTypesScope); + inheritedTypesScopes = (SimplTypesScope[]) baseTranslationsSet.toArray(); + } + + /** + * Create a new SimplTypesScope that defines how to translate xml tag names into class names of + * subclasses of ElementState. + * + * Set a new default package, and a set of defined translations. + * + * @param name + * Name of the TranslationSpace to be A key for use in the TranslationSpace registry. + * @param translations + * Set of initially defined translations for this. + * @param defaultPackgeName + */ + private SimplTypesScope(String name, Class... translations) + { + this(name, (SimplTypesScope[]) null, translations); + addSimplTypesScope(name); + } + + /** + * Create a new SimplTypesScope that defines how to translate xml tag names into class names of + * subclasses of ElementState. + * + * Set a new default package, and a set of defined translations. + * + * @param name + * Name of the TranslationSpace to be A key for use in the TranslationSpace registry. + * @param translation + * Set of initially defined translations for this. + */ + private SimplTypesScope(String name, ClassDescriptor... translation) + { + this(name, (SimplTypesScope[]) null, translation); + addSimplTypesScope(name); + } + + /** + * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add + * the array of translations, then, make the defaultPackageName available. + * + * @param name + * @param inheritedSimplTypesScopes + * @param translations + */ + private SimplTypesScope(String name, SimplTypesScope[] inheritedSimplTypesScopes, + Class[]... translations) + { + this(name, inheritedSimplTypesScopes); + addTranslations(translations); + } + + /** + * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add + * the array of translations, then, make the defaultPackageName available. + * + * @param name + * @param inheritedSimplTypesScopes + * @param translations + */ + private SimplTypesScope(String name, SimplTypesScope[] inheritedSimplTypesScopes, + ClassDescriptor[]... translations) + { + this(name, inheritedSimplTypesScopes); + addTranslations(translations); + } + + /** + * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add + * the array of translations, then, make the defaultPackageName available. + * + * @param name + * @param translations + * @param baseTranslations + */ + private SimplTypesScope(String name, Collection inheritedTranslationsSet, + Class[] translations) + { + this(name, inheritedTranslationsSet); + addTranslations(translations); + + addSimplTypesScope(name); + } + + /** + * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add + * the array of translations, then, make the defaultPackageName available. + * + * @param name + * @param inheritedTranslationsSet + * @param translations + */ + private SimplTypesScope(String name, Collection inheritedTranslationsSet, + ClassDescriptor[] translations) + { + this(name, inheritedTranslationsSet); + addTranslations(translations); + + addSimplTypesScope(name); + } + + /** + * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add + * the array of translations, then, make the defaultPackageName available. + * + * @param name + * @param inheritedSimplTypesScope + * @param translations A set of arrays of classes. + */ + private SimplTypesScope(String name, SimplTypesScope inheritedSimplTypesScope, + Class[]... translations) + { + this(name, inheritedSimplTypesScope); + addTranslations(translations); + + addSimplTypesScope(name); + } + + /** + * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add + * the array of translations, then, make the defaultPackageName available. + * + * @param name + * @param inheritedSimplTypesScope + * @param translations + */ + private SimplTypesScope(String name, SimplTypesScope inheritedSimplTypesScope, + ClassDescriptor[]... translations) + { + this(name, inheritedSimplTypesScope); + addTranslations(translations); + + addSimplTypesScope(name); + } + + /** + * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add + * the array of translations, then, make the defaultPackageName available. Map XML Namespace + * declarations. + * + * @param name + * @param nameSpaceDecls + * @param inheritedSimplTypesScopes + * @param translations + * @param defaultPackgeName + */ + private SimplTypesScope(String name, NameSpaceDecl[] nameSpaceDecls, + SimplTypesScope[] inheritedSimplTypesScopes, Class[] translations) + { + this(name, inheritedSimplTypesScopes, translations); + addNameSpaceDecls(nameSpaceDecls); + + addSimplTypesScope(name); + } + + /** + * Construct a new SimplTypesScope, with this name, using the baseTranslations first. Then, add + * the array of translations, then, make the defaultPackageName available. Map XML Namespace + * declarations. + * + * @param name + * @param nameSpaceDecls + * @param inheritedSimplTypesScopes + * @param translations + */ + private SimplTypesScope(String name, NameSpaceDecl[] nameSpaceDecls, + SimplTypesScope[] inheritedSimplTypesScopes, ClassDescriptor[] translations) + { + this(name, inheritedSimplTypesScopes, translations); + addNameSpaceDecls(nameSpaceDecls); + + addSimplTypesScope(name); + } + + /** + * Map XML Namespace ElementState subclasses to URIs. + * + * @param nameSpaceDecls + */ + private void addNameSpaceDecls(NameSpaceDecl[] nameSpaceDecls) + { + if (nameSpaceDecls != null) + for (NameSpaceDecl nsd : nameSpaceDecls) + { + registerNameSpaceDecl(nsd); + } + } + + /** + * Enter a NameSpaceDecl into nameSpaceClassesByURN. + * + * @param nsd + */ + private void registerNameSpaceDecl(NameSpaceDecl nsd) + { + nameSpaceClassesByURN.put(nsd.urn, nsd.esClass); + } + + /** + * Add translations, where each translation is defined by an actual Class object. We can get both + * the class name and the package name from the Class object. + * + * @param classes + */ + private void addTranslations(Class[]... arrayOfClasses) + { + if (arrayOfClasses != null) + { + int numClasses = arrayOfClasses.length; + + for (int i = 0; i < numClasses; i++) + { + if (arrayOfClasses[i] != null) + { + for (Class thatClass : arrayOfClasses[i]) + { + addTranslation(thatClass); + } + } + } + } + + allTypesScopes.put(name, this); + } + + /** + * Add translations, where each translation is defined by an actual Class object. We can get both + * the class name and the package name from the Class object. + * + * @param arrayOfClasses + */ + private void addTranslations(ClassDescriptor[]... arrayOfClasses) + { + if (arrayOfClasses != null) + { + int numClasses = arrayOfClasses.length; + + for (int i = 0; i < numClasses; i++) + { + if (arrayOfClasses[i] != null) + { + for (ClassDescriptor thatClass : arrayOfClasses[i]) + { + addTranslation(thatClass); + } + } + } + } + + allTypesScopes.put(name, this); + } + + /** + * Utility for composing SimplTypesScopes. Performs composition by value. That is, + * the entries are copied. + * + * Unlike in union(), if there are duplicates, they will override identical entries in this. + * + * @param inheritedTypesScope + */ + private void addTranslations(SimplTypesScope inheritedTypesScope) + { + if (inheritedTypesScope != null) + { + // copy map entries from inherited maps into new maps + updateMapWithValues(inheritedTypesScope.entriesByClassSimpleName, + entriesByClassSimpleName, "classSimpleName"); + updateMapWithValues(inheritedTypesScope.entriesByClassName, entriesByClassName, + "className"); + updateMapWithValues(inheritedTypesScope.entriesByTag, entriesByTag, "tagName"); + + HashMap> inheritedNameSpaceClassesByURN = inheritedTypesScope.nameSpaceClassesByURN; + if (inheritedNameSpaceClassesByURN != null) + { + for (String urn : inheritedNameSpaceClassesByURN.keySet()) + { + nameSpaceClassesByURN.put(urn, inheritedNameSpaceClassesByURN.get(urn)); + } + } + } + } + + /** + * Update the Map with all the entries in the inherited Map. + * + * @param inheritedMap + * @param warn + */ + private void updateMapWithValues( + Map> inheritedMap, + Map> newMap, String warn) + { + // XXX ANDRUID + ZACH -> concurrent modification exception can occur here (for loop) if + // inheritedMap is modified elsewhere + for (String key : inheritedMap.keySet()) + { + ClassDescriptor translationEntry = inheritedMap.get(key); + updateMapWithEntry(newMap, key, translationEntry, warn); + } + } + + /** + * Update the Map with the entry. + * + * @param newMap + * @param key + * @param translationEntry + * Must be non-null. + * @param warn + */ + private void updateMapWithEntry(Map> newMap, + String key, ClassDescriptor translationEntry, String warn) + { + ClassDescriptor existingEntry = newMap.get(key); + + // final boolean entryExists = existingEntry != null; + // final boolean newEntry = existingEntry != translationEntry; + + final boolean entryExists = existingEntry != null; + final boolean newEntry = !entryExists ? true + : existingEntry.getDescribedClass() != translationEntry.getDescribedClass(); + + if (newEntry) + { + if (entryExists) // look out for redundant entries + warning("Overriding " + warn + " " + key + " with " + translationEntry); + + newMap.put(key, translationEntry); + } + // if (entryExists && newEntry) // look out for redundant entries + // warning("Overriding " + warn + " " + key + " with " + translationEntry); + // + // if (/** !entryExists || **/ newEntry) + // newMap.put(key, translationEntry); + } + + /** + * Add a translation table entry for an ElementState derived sub-class. Assumes that the xmlTag + * can be derived automatically from the className, by translating case-based separators to + * "_"-based separators. + * + * @param classObj + * The object for the class. + */ + public void addTranslation(Class classObj) + { + // Enumerated types behave a bit differently. + if(classObj.isEnum()) + { + if(!this.enumerationsBySimpleName.containsKey(classSimpleName(classObj))) + { + EnumerationDescriptor ed; + try + { + // Add if it isnt there already. + ed = EnumerationDescriptor.get(classObj); + } + catch(SIMPLDescriptionException sde) + { + // We need to wrap this to not upset the API, for now. + throw new RuntimeException(sde); + } + + this.enumerationsByTag.put(ed.getTagName(), ed); + this.enumerationsBySimpleName.put(ed.getName(), ed); + + // Don't think we have other tags here, we really just need simple name + // But putting it here just in case. + ArrayList otherTags = ed.otherTags(); + if (otherTags != null) + { + for (String otherTag : otherTags) + { + if ((otherTag != null) && (!otherTag.isEmpty())) + { + enumerationsByTag.put(otherTag, ed); + } + } + } + } + } + else + { + // Add a class! + ClassDescriptor entry = ClassDescriptor.getClassDescriptor(classObj); + String tagName = entry.getTagName(); + + entriesByTag.put(entry.getTagName(), entry); + entriesByClassSimpleName.put(entry.getDescribedClassSimpleName(), entry); + entriesByClassName.put(classObj.getName(), entry); + + entriesByTLVId.put(entry.getTagName().hashCode(), entry); + entriesByBibTeXType.put(entry.getBibtexType(), entry); + + ArrayList otherTags = entry.otherTags(); + if (otherTags != null) + { + for (String otherTag : otherTags) + { + if ((otherTag != null) && (otherTag.length() > 0)) + { + entriesByTag.put(otherTag, entry); + entriesByTLVId.put(otherTag.hashCode(), entry); + } + } + } + } + } + + /** + * Given a shallow translation*, which is effectively a mock object with overridden or removed functionality + * and annotated with @simpl_inherit_parent_tag + * (For example: A translation with the deserializationPostHook implemented as an empty method) + * + * This method will: + * + * 1. Remove the translation class the "shallow translation" is meant to replace + * 2. Add the shallow translation to the type scope. + * + * Currently used for deserialization w/o dealing with file dependencies. + * Could also be used for testing, etc. + * @param classObj The Shallow Translation to use as an override. + */ + public void overrideWithShallowTranslation(Class classObj) + { + removeTranslation(correspondingClassFor(classObj)); + addTranslation(classObj); + } + // * You could even call it a ... Doppelganger, if you wanted to. + + + private Class correspondingClassFor(Class dummyObj) + { + ClassDescriptor entry = ClassDescriptor.getClassDescriptor(dummyObj); + String tagName = entry.getTagName(); + + ClassDescriptor corresp = entriesByTag.get(tagName); + + return corresp != null? corresp.getDescribedClass() : dummyObj; + } + + /** + * Removes a given translation from the Type Scope + * @param classObj The translation to remove. + */ + public void removeTranslation(Class classObj) + { + ClassDescriptor entry = ClassDescriptor.getClassDescriptor(classObj); + + for (SimplTypesScope simplTypesScope : allTypesScopes.values()) + { + simplTypesScope.removeTranslation(entry, classObj.getName()); + } + + this.removeTranslation(entry, classObj.getName()); + } + + private void removeTranslation(ClassDescriptor entry, String className) + { + entriesByTag.remove(entry.getTagName()); + entriesByClassSimpleName.remove(entry.getDescribedClassSimpleName()); + entriesByClassName.remove(className); + + entriesByTLVId.remove(entry.getTagName().hashCode()); + entriesByBibTeXType.remove(entry.getBibtexType()); + + ArrayList otherTags = entry.otherTags(); + if (otherTags != null) + { + for (String otherTag : otherTags) + { + if ((otherTag != null) && (otherTag.length() > 0)) + { + entriesByTag.remove(otherTag); + entriesByTLVId.remove(otherTag.hashCode()); + } + } + } + } + + + /** + * Add a translation table entry for an ElementState derived sub-class. Assumes that the xmlTag + * can be derived automatically from the className, by translating case-based separators to + * "_"-based separators. + * + * @param classObj + * The object for the class. + */ + public void addTranslation(ClassDescriptor classObj) + { + ClassDescriptor entry = classObj; + String tagName = entry.getTagName(); + + entriesByTag.put(entry.getTagName(), entry); + entriesByClassSimpleName.put(entry.getDescribedClassSimpleName(), entry); + entriesByClassName.put(classObj.getName(), entry); + + entriesByTLVId.put(entry.getTagName().hashCode(), entry); + entriesByBibTeXType.put(entry.getBibtexType(), entry); + + ArrayList otherTags = entry.otherTags(); + if (otherTags != null) + for (String otherTag : otherTags) + { + if ((otherTag != null) && (otherTag.length() > 0)) + { + entriesByTag.put(otherTag, entry); + entriesByTLVId.put(otherTag.hashCode(), entry); + } + } + } + + /** + * Look-up a Class object for the xmlTag, using translations in this, and in + * inherited SimplTypesScopes. Will use defaultPackage name here and, recursivley, in inherited + * scopes, as necessary. + * + * @param xmlTag + * XML node name that we're seeking a Class for. + * @return Class object, or null if there is no associated translation. + */ + public Class xmlTagToClass(String xmlTag) + { + ClassDescriptor entry = xmlTagToTranslationEntry(xmlTag); + return entry.isEmpty() ? null : entry.getDescribedClass(); + } + + /** + * Seek the entry associated with the tag. Recurse through inherited SimplTypesScopes, if + * necessary. + * + * @param xmlTag + * @return + */ + private ClassDescriptor xmlTagToTranslationEntry(String xmlTag) + { + return getClassDescriptorByTag(xmlTag); + } + + /** + * Get the Class object associated with this tag, if there is one. Unlike xmlTagToClass, this call + * will not generate a new blank NameEntry. + * + * @param tag + * @return + */ + public Class getClassByTag(String tag) + { + ClassDescriptor entry = getClassDescriptorByTag(tag); + + return (entry == null) ? null : entry.getDescribedClass(); + } + + public ClassDescriptor getClassDescriptorByTag(String tag) + { + return entriesByTag.get(tag); + } + + public ClassDescriptor getClassDescriptorByTlvId(int id) + { + return entriesByTLVId.get(id); + } + + public ClassDescriptor getClassDescriptorByTLVId(int tlvId) + { + return entriesByTLVId.get(tlvId); + } + + public ClassDescriptor getClassDescriptorByBibTeXType(String typeName) + { + return entriesByBibTeXType.get(typeName); + } + + /** + * Get the Class object associated with the provided class name, if there is one. Unlike + * xmlTagToClass, this call will not generate a new blank NameEntry. + * + * @param classSimpleName + * Simple name of the class (no package). + * @return + */ + public Class getClassBySimpleName(String classSimpleName) + { + ClassDescriptor entry = getClassDescriptorBySimpleName(classSimpleName); + return (entry == null) ? null : entry.getDescribedClass(); + } + + public ClassDescriptor getClassDescriptorBySimpleName(String classSimpleName) + { + return entriesByClassSimpleName.get(classSimpleName); + } + + public Class getClassByName(String className) + { + ClassDescriptor entry = entriesByClassName.get(className); + + return (entry == null) ? null : entry.getDescribedClass(); + } + + public ClassDescriptor getClassDescriptorByClassName(String className) + { + return entriesByClassName.get(className); + } + + public ArrayList> getAllClasses() + { + ArrayList> classes = new ArrayList>(); + Collection> classDescriptors = this + .getClassDescriptors(); + + for (SimplTypesScope typesScope : allTypesScopes.values()) + { + for (ClassDescriptor classDescriptor : typesScope.entriesByClassSimpleName + .values()) + { + classes.add(classDescriptor.getDescribedClass()); + } + } + return classes; + } + + /** + * Use this SimplTypesScope to lookup a class that has the same simple name as the argument + * passed in here. It may have a different full name, that is, a different package, which could be + * quite convenient for overriding with subclasses. + * + * @param thatClass + * @return + */ + public Class getClassBySimpleNameOfClass(Class thatClass) + { + return getClassBySimpleName(classSimpleName(thatClass)); + } + + /** + * Lookup the tag for the class in question, using this. + * + * @param thatClass + * @return + */ + public String getTag(Class thatClass) + { + return getTagBySimpleName(classSimpleName(thatClass)); + } + + public String getTagBySimpleName(String simpleName) + { + ClassDescriptor entry = entriesByClassSimpleName.get(simpleName); + + return (entry == null) ? null : entry.getTagName(); + } + + /** + * Derive the XML tag from the Class object, using camel case conversion, or the @simpl_tag + * annotation that may be present in a class declaration. + * + * @param thatClass + * @return + */ + private static String determineXMLTag(Class thatClass) + { + Annotation[] annotations = thatClass.getDeclaredAnnotations(); + for (Annotation annotation : annotations) + { + if (annotation.annotationType().equals(simpl_tag.class)) + { + return simpl_tag.class.cast(annotation).value(); + } + } + return XMLTools.getXmlTagName(thatClass.getSimpleName(), "State"); + } + + private String toStringCache; + + @Override + public String toString() + { + if (toStringCache == null) + { + toStringCache = "SimplTypesScope[" + name + "]"; + } + return toStringCache; + } + + /** + * Find the SimplTypesScope called name, if there is one. + * + * @param name + * @return + */ + public static SimplTypesScope lookup(String name) + { + return allTypesScopes.get(name); + } + + /** + * Unlike other get() methods in this class, this one is not a factory, but a simple accessor. It + * performs a lookup, but does not construct. + * + * @param name + * @return + */ + public static SimplTypesScope get(String name) + { + return lookup(name); + } + + /** + * Find an existing SimplTypesScope by this name, or create a new one. + * + * @param name + * the name of the SimplTypesScope + * @param translations + * a set of Classes to be used as a part of this SimplTypesScope + * @return + */ + public static SimplTypesScope get(String name, Class... translations) + { + SimplTypesScope result = lookup(name); + if (result == null) + { + synchronized (name) + { + result = lookup(name); + if (result == null) + { + result = new SimplTypesScope(name, translations); + } + } + } + return result; + } + + /** + * Find an existing SimplTypesScope by this name, or create a new one. Inherit from the previous + * SimplTypesScope, by including all mappings from there. + * + * If new translations are provided when the SimplTypesScope already exists in the static scope + * map, they are ignored. + * + * @param name + * @param inheritedTranslations + * @param translations + * @return + */ + public static SimplTypesScope get(String name, SimplTypesScope inheritedTranslations, + Class[]... translations) + { + SimplTypesScope result = lookup(name); + if (result == null) + { + synchronized (name) + { + result = lookup(name); + if (result == null) + result = new SimplTypesScope(name, inheritedTranslations, translations); + } + } + return result; + } + + /** + * Find an existing SimplTypesScope by this name, or create a new one. Inherit from the previous + * SimplTypesScope, by including all mappings from there. + * + * If new translations are provided when the SimplTypesScope already exists in the static scope + * map, they are ignored. + * + * @param name + * @param inheritedTranslations + * @param translations + * @return + */ + public static SimplTypesScope get(String name, SimplTypesScope inheritedTranslations, + Class... translations) + { + SimplTypesScope result = lookup(name); + if (result == null) + { + synchronized (name) + { + result = lookup(name); + if (result == null) + result = new SimplTypesScope(name, inheritedTranslations, translations); + } + } + return result; + } + + /** + * Find an existing SimplTypesScope by this name, or create a new one. Build on a previous + * SimplTypesScope, by including all mappings from there. Add just a single new class. + * + * @param name + * @param inheritedTranslations + * @param translation + * @return + */ + public static SimplTypesScope get(String name, SimplTypesScope inheritedTranslations, + Class translation) + { + SimplTypesScope result = lookup(name); + if (result == null) + { + synchronized (name) + { + result = lookup(name); + if (result == null) + result = new SimplTypesScope(name, inheritedTranslations, translation); + } + } + return result; + } + + /** + * Find an existing SimplTypesScope by this name, or create a new one. Add just a single new + * class. + * + * @param name + * @param translation + * @return + */ + public static SimplTypesScope get(String name, Class translation) + { + return get(name, null, translation); + } + + /** + * Find an existing SimplTypesScope by this name, or create a new one. Build on the previous + * SimplTypesScope, by including all mappings from there. + * + * @param name + * the name of the SimplTypesScope to acquire. + * @param translations + * an array of translations to add to the scope. + * @param inheritedTranslations + * a list of previous translation scopes to build upon. + * @return + */ + public static SimplTypesScope get(String name, SimplTypesScope[] inheritedTranslationsSet, + Class... translations) + { + SimplTypesScope result = lookup(name); + if (result == null) + { + synchronized (name) + { + result = lookup(name); + if (result == null) + result = new SimplTypesScope(name, inheritedTranslationsSet, translations); + } + } + return result; + } + + /** + * Find an existing SimplTypesScope by this name, or create a new one. Build on the previous + * SimplTypesScope, by including all mappings from there. + * + * @param name + * the name of the SimplTypesScope to acquire. + * @param translations + * an array of translations to add to the scope. + * @param inheritedTranslations + * a list of previous translation scopes to build upon. + * @return + */ + public static SimplTypesScope get(String name, SimplTypesScope[] inheritedTranslationsSet, + Class[]... translations) + { + SimplTypesScope result = lookup(name); + if (result == null) + { + synchronized (name) + { + result = lookup(name); + if (result == null) + result = new SimplTypesScope(name, inheritedTranslationsSet, translations); + } + } + return result; + } + + public static SimplTypesScope get(String name, SimplTypesScope inheritedTranslations0, + SimplTypesScope inheritedTranslations1, Class... translations) + { + SimplTypesScope[] inheritedArray = new SimplTypesScope[2]; + inheritedArray[0] = inheritedTranslations0; + inheritedArray[1] = inheritedTranslations1; + return get(name, inheritedArray, translations); + } + + public static SimplTypesScope get(String name, NameSpaceDecl[] nameSpaceDecls, + Class... translations) + { + return get(name, nameSpaceDecls, null, translations); + } + + /** + * Find an existing SimplTypesScope by this name, or create a new one. Build on a set of + * inherited SimplTypesScopes, by including all mappings from them. + * + * @param name + * @param nameSpaceDecls + * Array of ElementState class + URI key map entries for handling XML Namespaces. + * @param inheritedTranslationsSet + * @param translations + * @param defaultPackageName + * @return + */ + public static SimplTypesScope get(String name, NameSpaceDecl[] nameSpaceDecls, + SimplTypesScope[] inheritedTranslationsSet, Class... translations) + { + SimplTypesScope result = lookup(name); + if (result == null) + { + synchronized (name) + { + result = lookup(name); + if (result == null) + result = new SimplTypesScope(name, nameSpaceDecls, inheritedTranslationsSet, + translations); + } + } + return result; + } + + /** + * Find an existing SimplTypesScope by this name, or create a new one. Build on a set of + * inherited SimplTypesScopes, by including all mappings from them. + * + * @param name + * @param inheritedTranslations + * @return + */ + public static SimplTypesScope get(String name, SimplTypesScope... inheritedTranslations) + { + return get(name, inheritedTranslations, (Class []) null); + } + + /** + * Find an existing SimplTypesScope by this name, or create a new one. Build on a set of + * inherited SimplTypesScopes, by including all mappings from them. + * + * @param name + * @param inheritedTranslationsSet + * @param translations + * @return + */ + public static SimplTypesScope get(String name, + Collection inheritedTranslationsSet, Class... translations) + { + SimplTypesScope result = lookup(name); + if (result == null) + { + synchronized (name) + { + result = lookup(name); + if (result == null) + result = new SimplTypesScope(name, inheritedTranslationsSet, translations); + } + } + return result; + } + + protected HashMap> entriesByClassSimpleName() + { + return entriesByClassSimpleName; + } + + public HashMap> entriesByClassName() + { + return entriesByClassName; + } + + public HashSet addClassNamesToHashSet(HashSet hashSet) + { + if (inheritedTypesScopes != null) + { + for (SimplTypesScope inheritedTScope : inheritedTypesScopes) + { + inheritedTScope.generateImports(hashSet); + } + } + this.generateImports(hashSet); + return hashSet; + } + + protected void generateImports(HashSet hashSet) + { + for (String className : entriesByClassName.keySet()) + { + hashSet.add(className); + } + } + + private ArrayList> classDescriptors; + + // FIXME -- implement this! + public ArrayList> getClassDescriptors() + { + ArrayList> result = classDescriptors; + if (result == null) + { + result = new ArrayList>(entriesByTag.values()); // we use entriesByTag so that overriding works well. + this.classDescriptors = result; + } + return result; + } + + public void clearCachedClassDescriptors() + { + classDescriptors = null; + } + + /** + * Get the Scalar Type corresponding to the Class. + * + * @param thatClass + * @return Type associated with thatClass + */ + ScalarType getType(Class thatClass) + { + return TypeRegistry.getScalarType(thatClass); + } + + /** + * Lookup a NameSpace ElementState subclass, with a URN as the key. + * + * @param urn + * @return + */ + public Class lookupNameSpaceByURN(String urn) + { + return nameSpaceClassesByURN.get(urn); + } + + /** + * + * @return The unique name of this. + */ + public String getName() + { + return name; + } + + public static final String BASIC_TRANSLATIONS = "basic_translations"; + + private void addSimplTypesScope(String name) + { + synchronized(allTypesScopes) + { + if(!allTypesScopes.containsKey(name)) + { + // TODO: Concurrency? yo. + allTypesScopes.put(name, this); + System.out.println(""); + debug("... Initializing ..."); + } + else + { + //throw new RuntimeException("OH NO EVERYTHING IS AMISS FOR: " + name); + } + } + } + + + public Object deserialize(File file, TranslationContext translationContext, + DeserializationHookStrategy deserializationHookStrategy, Format format) + throws SIMPLTranslationException + { + PullDeserializer pullDeserializer = PullDeserializer.getDeserializer(this, translationContext, + deserializationHookStrategy, format); + return pullDeserializer.parse(file); + } + + public Object deserialize(File file, TranslationContext translationContext, Format format) + throws SIMPLTranslationException + { + return deserialize(file, translationContext, null, format); + } + + public Object deserialize(File file, Format format) throws SIMPLTranslationException + { + TranslationContext translationContext= new TranslationContext(); + Object obj = deserialize(file, translationContext, null, format); + return obj; + } + + public Object deserialize(File file, DeserializationHookStrategy deserializationHookStrategy, + Format format) throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + Object obj = deserialize(file, translationContext, deserializationHookStrategy, format); + return obj; + } + + public Object deserialize(ParsedURL parsedURL, + DeserializationHookStrategy deserializationHookStrategy, Format format) + throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + Object obj = deserialize(parsedURL, translationContext, deserializationHookStrategy, format); + return obj; + } + + public Object deserialize(ParsedURL parsedURL, TranslationContext translationContext, + Format format) throws SIMPLTranslationException + { + return deserialize(parsedURL, translationContext, null, format); + } + + public Object deserialize(ParsedURL parsedURL, Format format) throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + Object obj = deserialize(parsedURL, translationContext, null, format); + return obj; + } + + public Object deserialize(ParsedURL parsedURL, TranslationContext translationContext, + DeserializationHookStrategy deserializationHookStrategy, Format format) + throws SIMPLTranslationException + { + PullDeserializer pullDeserializer = PullDeserializer.getDeserializer(this, translationContext, + deserializationHookStrategy, format); + return pullDeserializer.parse(parsedURL); + } + + public Object deserialize(InputStream inputStream, + DeserializationHookStrategy deserializationHookStrategy, Format format) + throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + Object obj = deserialize(inputStream, translationContext, deserializationHookStrategy, format, + null); + return obj; + } + + public Object deserialize(InputStream inputStream, + DeserializationHookStrategy deserializationHookStrategy, Format format, Charset charSet) + throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + Object obj = deserialize(inputStream, translationContext, deserializationHookStrategy, format, + charSet); + return obj; + } + + public Object deserialize(InputStream inputStream, TranslationContext translationContext, + Format format) throws SIMPLTranslationException + { + return deserialize(inputStream, translationContext, null, format, null); + } + + public Object deserialize(InputStream inputStream, TranslationContext translationContext, + Format format, Charset charSet) throws SIMPLTranslationException + { + return deserialize(inputStream, translationContext, null, format, charSet); + } + + public Object deserialize(InputStream inputStream, Format format) + throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + Object obj = deserialize(inputStream, translationContext, null, format, null); + return obj; + } + + public Object deserialize(InputStream inputStream, Format format, Charset charSet) + throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + Object obj = deserialize(inputStream, translationContext, null, format, charSet); + return obj; + } + +public Object deserialize(InputStream inputStream, TranslationContext translationContext, + DeserializationHookStrategy deserializationHookStrategy, Format format, Charset charSet) + throws SIMPLTranslationException +{ + PullDeserializer pullDeserializer = PullDeserializer.getDeserializer(this, translationContext, + deserializationHookStrategy, format); + if(charSet != null) + { + return pullDeserializer.parse(inputStream, charSet); + } + else + { + return pullDeserializer.parse(inputStream); + } +} + + public Object deserialize(URL url, Format format) throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + Object obj = deserialize(new ParsedURL(url), translationContext, null, format); + return obj; + } + + public Object deserialize(CharSequence charSequence, TranslationContext translationContext, + DeserializationHookStrategy deserializationHookStrategy, StringFormat stringFormat) + throws SIMPLTranslationException + { + StringPullDeserializer pullDeserializer = PullDeserializer.getStringDeserializer(this, + translationContext, deserializationHookStrategy, stringFormat); + return pullDeserializer.parse(charSequence); + } + + public Object deserialize(CharSequence charSequence, + DeserializationHookStrategy deserializationHookStrategy, StringFormat stringFormat) + throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + StringPullDeserializer pullDeserializer = PullDeserializer.getStringDeserializer(this, + translationContext, deserializationHookStrategy, stringFormat); + return pullDeserializer.parse(charSequence); + } + + public Object deserialize(CharSequence charSequence, TranslationContext translationContext, + StringFormat stringFormat) throws SIMPLTranslationException + { + return deserialize(charSequence, translationContext, null, stringFormat); + } + + public Object deserialize(CharSequence charSequence, StringFormat stringFormat) + throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + Object obj = deserialize(charSequence, translationContext, null, stringFormat); + return obj; + } + + public Object deserialize(byte[] byteArray, TranslationContext translationContext, + DeserializationHookStrategy deserializationHookStrategy, BinaryFormat binaryFormat) + throws SIMPLTranslationException + { + BinaryPullDeserializer binaryPullDeserializer = PullDeserializer.getBinaryDeserializer(this, + translationContext, deserializationHookStrategy, binaryFormat); + return binaryPullDeserializer.parse(byteArray); + } + + public static SimplTypesScope getBasicTranslations() + { + return get(BASIC_TRANSLATIONS, SimplTypesScope.class, FieldDescriptor.class, + ClassDescriptor.class); + } + + public static SimplTypesScope augmentTranslationScope(SimplTypesScope simplTypesScope) + { + ArrayList> allClasses = simplTypesScope.getAllClasses(); + Collection> augmentedClasses = augmentTranslationScope(allClasses).values(); + + Class[] augmentedClassesArray = augmentedClasses + .toArray(new Class[augmentedClasses.size()]); + + return new SimplTypesScope(simplTypesScope.getName(), augmentedClassesArray); + } + + private static HashMap> augmentTranslationScope(ArrayList> allClasses) + { + HashMap> augmentedClasses = new HashMap>(); + for (Class thatClass : allClasses) + { + augmentSimplTypesScope(thatClass, augmentedClasses); + } + return augmentedClasses; + } + + private static void augmentSimplTypesScope(Class thatClass, + HashMap> augmentedClasses) + { + if (augmentedClasses.put(thatClass.getSimpleName(), thatClass) != null) + return; + + if (thatClass.getSuperclass() != ElementState.class) + { + augmentSimplTypesScope(thatClass.getSuperclass().asSubclass(ElementState.class), + augmentedClasses); + } + + ClassDescriptor thatClassDescriptor = ClassDescriptor + .getClassDescriptor(thatClass); + + HashMapArrayList fieldDescriptors = thatClassDescriptor + .getFieldDescriptorsByFieldName(); + + if (fieldDescriptors.size() > 0) + { + thatClassDescriptor.resolvePolymorphicAnnotations(); + + for (FieldDescriptor fieldDescriptor : fieldDescriptors) + { + if (fieldDescriptor.isNested()) + { + augmentSimplTypesScope(fieldDescriptor.getFieldType().asSubclass(ElementState.class), + augmentedClasses); + } + else + { + if (fieldDescriptor.isCollection() && !fieldDescriptor.isPolymorphic()) + { + ArrayList> genericClasses = XMLTools.getGenericParameters(fieldDescriptor + .getField()); + + for (Class genericClass : genericClasses) + { + if (genericClass != null && ElementState.class.isAssignableFrom(genericClass)) + { + augmentSimplTypesScope(genericClass.asSubclass(ElementState.class), + augmentedClasses); + } + } + } + else if (fieldDescriptor.isPolymorphic()) + { + Collection polymorphDescriptors = fieldDescriptor + .getPolymorphicClassDescriptors(); + + if (polymorphDescriptors != null) + { + for (ClassDescriptor classDescriptor : polymorphDescriptors) + { + augmentSimplTypesScope(classDescriptor.getDescribedClass(), augmentedClasses); + } + } + } + } + } + } + } + + public void augment() + { + Class[] augmentedClassesArray = getClassesArray(this); + + this.addTranslations(augmentedClassesArray); + } + + private static Class[] getClassesArray(SimplTypesScope simplTypesScope) + { + ArrayList> allClasses = simplTypesScope.getAllClasses(); + Collection> augmentedClasses = augmentTranslationScope(allClasses).values(); + + Class[] augmentedClassesArray = augmentedClasses + .toArray(new Class[augmentedClasses.size()]); + return augmentedClassesArray; + } + + /** + * @return the performFilters + */ + public boolean isPerformFilters() + { + return performFilters; + } + + /** + * @param performFilters + * the performFilters to set + */ + public void setPerformFilters(boolean performFilters) + { + this.performFilters = performFilters; + } + + /** + * Augment the given SimplTypesScope and return the augmented one + * + * @param simplTypesScope + * @return + */ + public static SimplTypesScope augmentTranslationScopeWithClassDescriptors( + SimplTypesScope simplTypesScope) + { + Collection> allClassDescriptors = simplTypesScope + .getClassDescriptors(); + + ArrayList> allClasses = simplTypesScope + .getAllClassDescriptors(); + Collection> augmentedClasses = augmentSimplTypesScopeWithClassDescriptors( + allClasses).values(); + + ClassDescriptor[] augmentedClassesArray = augmentedClasses + .toArray(new ClassDescriptor[augmentedClasses.size()]); + + return new SimplTypesScope(simplTypesScope.getName(), augmentedClassesArray); + } + + /** + * augment the given the list of classes + * + * @param allClasses + * @return + */ + private static HashMap> augmentSimplTypesScopeWithClassDescriptors( + ArrayList> allClasses) + { + HashMap> augmentedClasses = new HashMap>(); + for (ClassDescriptor thatClass : allClasses) + { + augmentSimplTypesScope(thatClass, augmentedClasses); + } + return augmentedClasses; + } + + /** + * augment the given ClassDescriptor + * + * @param thatClass + * @param augmentedClasses + */ + private static void augmentSimplTypesScope(ClassDescriptor thatClass, + HashMap> augmentedClasses) + { + if (augmentedClasses.put(thatClass.getDescribedClassSimpleName(), thatClass) != null) + return; + + ClassDescriptor superClass = thatClass.getSuperClass(); + if (superClass != null && !"ElementState".equals(superClass.getDescribedClassSimpleName())) + { + augmentSimplTypesScope(superClass, augmentedClasses); + } + + HashMapArrayList fieldDescriptors = thatClass + .getFieldDescriptorsByFieldName(); + + if (fieldDescriptors.size() > 0) + { + thatClass.resolvePolymorphicAnnotations(); + + for (FieldDescriptor fieldDescriptor : fieldDescriptors) + { + if (fieldDescriptor.isNested()) + { + augmentSimplTypesScope(fieldDescriptor.getElementClassDescriptor(), augmentedClasses); + } + else + { + if (fieldDescriptor.isCollection() && !fieldDescriptor.isPolymorphic()) + { + ArrayList> genericClasses = XMLTools.getGenericParameters(fieldDescriptor + .getField()); + + for (Class genericClass : genericClasses) + { + if (genericClass != null && ElementState.class.isAssignableFrom(genericClass)) + { + augmentSimplTypesScope(ClassDescriptor.getClassDescriptor(genericClass + .asSubclass(ElementState.class)), augmentedClasses); + } + } + } + else if (fieldDescriptor.isPolymorphic()) + { + Collection polymorphDescriptors = fieldDescriptor + .getPolymorphicClassDescriptors(); + + if (polymorphDescriptors != null) + { + for (ClassDescriptor classDescriptor : polymorphDescriptors) + { + augmentSimplTypesScope(classDescriptor, augmentedClasses); + } + } + } + } + } + } + } + + /** + * Method returning all the class descriptors corresponds to all the translation Scopes + * + * @return + */ + public ArrayList> getAllClassDescriptors() + { + ArrayList> classes = new ArrayList>(); + + for (SimplTypesScope simplTypesScope : allTypesScopes.values()) + { + for (ClassDescriptor classDescriptor : simplTypesScope.entriesByTag + .values()) + { + classes.add(classDescriptor); + } + } + return classes; + } + + /** + * Make a new SimplTypesScope from a subset of this, making sure that the class of all entries in + * the subset is either superClassCriterion or a subclass thereof. + * + * @param newName + * Name for new SimplTypesScope. + * @param superClassCriterion + * Super class discriminant for all classes in the subset. + * + * @return New or existing SimplTypesScope with subset of classes in this, based on + * assignableCriterion. + */ + public SimplTypesScope getAssignableSubset(String newName, Class superClassCriterion) + { + SimplTypesScope result = lookup(newName); + if (result == null) + { + synchronized (entriesByClassName) + { + result = lookup(newName); + if (result == null) + { + result = new SimplTypesScope(newName); + addSimplTypesScope(newName); + for (ClassDescriptor classDescriptor : entriesByClassName.values()) + { + Class thatClass = classDescriptor.getDescribedClass(); + if (superClassCriterion.isAssignableFrom(thatClass)) + result.addTranslation(classDescriptor); + } + } + } + } + return result; + } + + /** + * Make a new SimplTypesScope from a subset of this, making sure that the class of all entries in + * never either superClassCriterion or a subclass thereof. + * + * @param newName + * Name for new SimplTypesScope. + * @param superClassCriterion + * Super class discriminant for all classes to remove from the subset. + * + * @return New or existing SimplTypesScope with subset of classes in this, based on + * assignableCriterion. + */ + public SimplTypesScope getSubtractedSubset(String newName, Class superClassCriterion) + { + SimplTypesScope result = lookup(newName); + if (result == null) + { + synchronized (entriesByClassName) + { + result = lookup(newName); + if (result == null) + { + result = new SimplTypesScope(newName); + addSimplTypesScope(newName); + for (ClassDescriptor classDescriptor : entriesByClassName.values()) + { + Class thatClass = classDescriptor.getDescribedClass(); + if (!superClassCriterion.isAssignableFrom(thatClass)) + result.addTranslation(classDescriptor); + } + } + } + } + return result; + } + + /** + * This will switch on the graph serialization + */ + public static void enableGraphSerialization() + { + graphSwitch = GRAPH_SWITCH.ON; + } + + /** + * This will switch on the graph serialization + */ + public static void disableGraphSerialization() + { + graphSwitch = GRAPH_SWITCH.OFF; + } + + /** + * Rebuild structures after serializing only some fields. + */ + @Override + public void deserializationPostHook(TranslationContext translationContext, Object object) + { + for (ClassDescriptor classDescriptor : entriesByTag.values()) + { + entriesByClassName.put(classDescriptor.getName(), classDescriptor); + String simpleName = classDescriptor.getDescribedClassSimpleName(); + entriesByClassSimpleName.put(simpleName, classDescriptor); + } + if (allTypesScopes.containsKey(name)) + warning("REPLACING another SimplTypesScope of the SAME NAME during deserialization!\t" + + name); + allTypesScopes.put(name, this); + } + + /** + * + * @param object + * @param outputStream + * @param bibtex + * @throws SIMPLTranslationException + */ + public static void serialize(Object object, OutputStream outputStream, Format format) throws SIMPLTranslationException + { + FormatSerializer serializer = FormatSerializer.getSerializer(format); + serializer.serialize(object, outputStream); + } + + /** + * + * @param object + * @param outputStream + * @param format + * @param translationContext + * @throws SIMPLTranslationException + */ + public static void serialize(Object object, OutputStream outputStream, Format format, TranslationContext translationContext) throws SIMPLTranslationException + { + FormatSerializer serializer = FormatSerializer.getSerializer(format); + serializer.serialize(object, outputStream, translationContext); + } + + /** + * Static method for serializing an object. accepts translation context which a user can supply to + * pass in additional information for the serialization method to use + * + * @param object + * @param stringBuilder + * @param format + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + public static StringBuilder serialize(Object object, StringFormat stringFormat, + TranslationContext translationContext) throws SIMPLTranslationException + { + StringSerializer stringSerializer = FormatSerializer.getStringSerializer(stringFormat); + return stringSerializer.serialize(object, translationContext); + } + + /** + * Static method for serializing an object. accepts translation context which a user can supply to + * pass in additional information for the serialization method to use + * + * @param object + * @param stringBuilder + * @param format + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + public static void serialize(Object object, StringBuilder stringBuilder, + StringFormat stringFormat, TranslationContext translationContext) + throws SIMPLTranslationException + { + StringSerializer stringSerializer = FormatSerializer.getStringSerializer(stringFormat); + stringSerializer.serialize(object, stringBuilder, translationContext); + } + + /** + * Static method for serializing an object. accepts translation context which a user can supply to + * pass in additional information for the serialization method to use + * + * @param object + * @param appendable + * @param format + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + public static void serialize(Object object, Appendable appendable, StringFormat stringFormat, + TranslationContext translationContext) throws SIMPLTranslationException + { + StringSerializer stringSerializer = FormatSerializer.getStringSerializer(stringFormat); + stringSerializer.serialize(object, appendable, translationContext); + } + + public static void serializeOut(Object object, String message, StringFormat stringFormat) + { + System.out.print(message); + System.out.print(':'); + try + { + serialize(object, System.out, stringFormat); + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Static method for serializing an object to the defined format. TranslationContext is + * automatically initialized to handle graphs if enabled + * + * @param object + * @param appendable + * @param format + * @throws SIMPLTranslationException + * @throws IOException + */ + public static void serialize(Object object, Appendable appendable, StringFormat stringFormat) + throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + serialize(object, appendable, stringFormat, translationContext); + } + + /** + * Static method for serializing an object to the defined format. TranslationContext is + * automatically initialized to handle graphs if enabled + * + * @param object + * @param stringBuilder + * @param stringFormat + * @throws SIMPLTranslationException + * @throws IOException + */ + public static StringBuilder serialize(Object object, StringFormat stringFormat) + throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + StringBuilder sb = serialize(object, stringFormat, translationContext); + return sb; + } + + /** + * Static method for serializing an object to the defined format. TranslationContext is + * automatically initialized to handle graphs if enabled + * + * @param object + * @param stringBuilder + * @param stringFormat + * @throws SIMPLTranslationException + * @throws IOException + */ + public static void serialize(Object object, StringBuilder stringBuilder, StringFormat stringFormat) + throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + serialize(object, stringBuilder, stringFormat, translationContext); + } + + /** + * Static method for serializing an object. accepts translation context which a user can supply to + * pass in additional information for the serialization method to use + * + * @param object + * @param appendable + * @param format + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + public static void serialize(Object object, File file, Format format, + TranslationContext translationContext) throws SIMPLTranslationException + { + FormatSerializer formatSerializer = FormatSerializer.getSerializer(format); + formatSerializer.serialize(object, file, translationContext); + } + + /** + * Static method for serializing an object to the defined format. TranslationContext is + * automatically initialized to handle graphs if enabled + * + * @param object + * @param stringBuilder + * @param stringFormat + * @throws SIMPLTranslationException + * @throws IOException + */ + public static void serialize(Object object, File file, Format format) + throws SIMPLTranslationException + { + TranslationContext translationContext = new TranslationContext(); + serialize(object, file, format, translationContext); + } +} diff --git a/simplCore/src/ecologylab/serialization/TranslationContext.java b/simplCore/src/ecologylab/serialization/TranslationContext.java index 230dad9e..8c19428c 100644 --- a/simplCore/src/ecologylab/serialization/TranslationContext.java +++ b/simplCore/src/ecologylab/serialization/TranslationContext.java @@ -1,345 +1,345 @@ -package ecologylab.serialization; - -import java.io.File; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; - -import ecologylab.collections.MultiMap; -import ecologylab.generic.Debug; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH; - -/** - * - * @author nabeelshahzad - * - */ -public class TranslationContext extends Debug implements ScalarUnmarshallingContext, FieldTypes -{ - - public static final String SIMPL_NAMESPACE = " xmlns:simpl=\"http://ecologylab.net/research/simplGuide/serialization/index.html\""; - - public static final String SIMPL = "simpl"; - - public static final String REF = "ref"; - - public static final String ID = "id"; - - public static final String SIMPL_ID = "simpl:id"; - - public static final String SIMPL_REF = "simpl:ref"; - - public static final String JSON_SIMPL_ID = "simpl.id"; - - public static final String JSON_SIMPL_REF = "simpl.ref"; - - private MultiMap marshalledObjects; - - private MultiMap visitedElements; - - private MultiMap needsAttributeHashCode; - - private HashMap unmarshalledObjects; - - protected ParsedURL baseDirPurl; - - protected File baseDirFile; - - protected String delimiter = ","; - - /** - * - */ - public TranslationContext() - { - - } - - /** - * - * @param fileDirContext - */ - public TranslationContext(File fileDirContext) - { - if (fileDirContext != null) - setBaseDirFile(fileDirContext); - } - - /** - * - * @param purlContext - */ - public TranslationContext(ParsedURL purlContext) - { - this.baseDirPurl = purlContext; - if (purlContext.isFile()) - this.baseDirFile = purlContext.file(); - } - - /** - * - * @param fileDirContext - */ - public void setBaseDirFile(File fileDirContext) - { - this.baseDirFile = fileDirContext; - this.baseDirPurl = new ParsedURL(fileDirContext); - } - - public void initializeMultiMaps() - { - marshalledObjects = new MultiMap(); - visitedElements = new MultiMap(); - needsAttributeHashCode = new MultiMap(); - unmarshalledObjects = new HashMap(); - } - - /** - * - * @param value - * @param elementState - */ - public void markAsUnmarshalled(String value, Object elementState) - { - if (unmarshalledObjects == null) - initializeMultiMaps(); - this.unmarshalledObjects.put(value, elementState); - } - - public void resolveGraph(Object object) - { - if (visitedElements == null) - initializeMultiMaps(); - - resolveGraphRecursvie(object); - } - - /** - * - * @param elementState - */ - public void resolveGraphRecursvie(Object elementState) - { - if (SimplTypesScope.graphSwitch == GRAPH_SWITCH.ON) - { - // this.visitedElements.put(System.identityHashCode(elementState), elementState); - this.visitedElements.put(elementState.hashCode(), elementState); - - ClassDescriptor.getClassDescriptor(elementState); - - ArrayList elementFieldDescriptors = ClassDescriptor - .getClassDescriptor(elementState).elementFieldDescriptors(); - - for (FieldDescriptor elementFieldDescriptor : elementFieldDescriptors) - { - Object thatReferenceObject = null; - Field childField = elementFieldDescriptor.getField(); - try - { - thatReferenceObject = childField.get(elementState); - } - catch (IllegalAccessException e) - { - debugA("WARNING re-trying access! " + e.getStackTrace()[0]); - childField.setAccessible(true); - try - { - thatReferenceObject = childField.get(elementState); - } - catch (IllegalAccessException e1) - { - error("Can't access " + childField.getName()); - e1.printStackTrace(); - } - } - catch (Exception e) - { - System.out.println(e); - } - // ignore null reference objects - if (thatReferenceObject == null) - continue; - - FieldType childFdType = elementFieldDescriptor.getType(); - - Collection thatCollection; - switch (childFdType) - { - case COLLECTION_ELEMENT: - case COLLECTION_SCALAR: - case MAP_ELEMENT: - case MAP_SCALAR: - thatCollection = XMLTools.getCollection(thatReferenceObject); - break; - default: - thatCollection = null; - break; - } - - if (thatCollection != null && (thatCollection.size() > 0)) - { - for (Object next : thatCollection) - { - if (next instanceof Object) - { - Object compositeElement = next; - - if (this.alreadyVisited(compositeElement)) - { - // this.needsAttributeHashCode.put(System.identityHashCode(compositeElement), - // compositeElement); - this.needsAttributeHashCode.put(compositeElement.hashCode(), compositeElement); - } - else - { - this.resolveGraph(compositeElement); - } - } - } - } - else if (thatReferenceObject instanceof Object) - { - Object compositeElement = thatReferenceObject; - - if (this.alreadyVisited(compositeElement)) - { - // this.needsAttributeHashCode.put(System.identityHashCode(compositeElement), - // compositeElement); - this.needsAttributeHashCode.put(compositeElement.hashCode(), compositeElement); - } - else - { - resolveGraph(compositeElement); - } - } - } - } - } - - /** - * - * @param elementState - * @return - */ - public boolean alreadyVisited(Object elementState) - { - if (unmarshalledObjects == null) - initializeMultiMaps(); - - return this.visitedElements.contains(elementState.hashCode(), elementState) != -1; - } - - /** - * - * @param object - */ - public void mapObject(Object object) - { - if (SimplTypesScope.graphSwitch == GRAPH_SWITCH.ON) - { - if (object != null) - this.marshalledObjects.put(object.hashCode(), object); - } - } - - /** - * - * @param compositeObject - * @return - */ - public boolean alreadyMarshalled(Object compositeObject) - { - if (compositeObject == null) - return false; - - return this.marshalledObjects.contains(compositeObject.hashCode(), compositeObject) != -1; - } - - /** - * - * @param elementState - * @return - */ - public boolean needsHashCode(Object elementState) - { - return this.needsAttributeHashCode.contains(elementState.hashCode(), elementState) != -1; - } - - /** - * - * @return - */ - public boolean isGraph() - { - return this.needsAttributeHashCode.size() > 0; - } - - /** - * - * @param value - * @return - */ - public Object getFromMap(String value) - { - - return this.unmarshalledObjects.get(value); - } - - /** - * - */ - @Override - public ParsedURL purlContext() - { - return (baseDirPurl != null) ? baseDirPurl : (baseDirFile != null) ? new ParsedURL(baseDirFile) - : null; - } - - public String getSimplId(Object object) - { - Integer objectHashCode = object.hashCode(); - Integer orderedIndex = marshalledObjects.contains(objectHashCode, object); - - if (orderedIndex > 0) - return objectHashCode.toString() + "," + orderedIndex.toString(); - else - return objectHashCode.toString(); - } - - /** - * - */ - @Override - public File fileContext() - { - return (baseDirFile != null) ? baseDirFile : (baseDirPurl != null) ? baseDirPurl.file() : null; - } - - /** - * - * @return - */ - public String getDelimiter() - { - return delimiter; - } - - void clean() - { - if (marshalledObjects != null) - marshalledObjects.clear(); - if (visitedElements != null) - visitedElements.clear(); - if (needsAttributeHashCode != null) - needsAttributeHashCode.clear(); - if (needsAttributeHashCode != null) - unmarshalledObjects.clear(); - - baseDirPurl = null; - baseDirFile = null; - delimiter = ","; - } - +package ecologylab.serialization; + +import java.io.File; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; + +import ecologylab.collections.MultiMap; +import ecologylab.generic.Debug; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH; + +/** + * + * @author nabeelshahzad + * + */ +public class TranslationContext extends Debug implements ScalarUnmarshallingContext, FieldTypes +{ + + public static final String SIMPL_NAMESPACE = " xmlns:simpl=\"http://ecologylab.net/research/simplGuide/serialization/index.html\""; + + public static final String SIMPL = "simpl"; + + public static final String REF = "ref"; + + public static final String ID = "id"; + + public static final String SIMPL_ID = "simpl:id"; + + public static final String SIMPL_REF = "simpl:ref"; + + public static final String JSON_SIMPL_ID = "simpl.id"; + + public static final String JSON_SIMPL_REF = "simpl.ref"; + + private MultiMap marshalledObjects; + + private MultiMap visitedElements; + + private MultiMap needsAttributeHashCode; + + private HashMap unmarshalledObjects; + + protected ParsedURL baseDirPurl; + + protected File baseDirFile; + + protected String delimiter = ","; + + /** + * + */ + public TranslationContext() + { + + } + + /** + * + * @param fileDirContext + */ + public TranslationContext(File fileDirContext) + { + if (fileDirContext != null) + setBaseDirFile(fileDirContext); + } + + /** + * + * @param purlContext + */ + public TranslationContext(ParsedURL purlContext) + { + this.baseDirPurl = purlContext; + if (purlContext.isFile()) + this.baseDirFile = purlContext.file(); + } + + /** + * + * @param fileDirContext + */ + public void setBaseDirFile(File fileDirContext) + { + this.baseDirFile = fileDirContext; + this.baseDirPurl = new ParsedURL(fileDirContext); + } + + public void initializeMultiMaps() + { + marshalledObjects = new MultiMap(); + visitedElements = new MultiMap(); + needsAttributeHashCode = new MultiMap(); + unmarshalledObjects = new HashMap(); + } + + /** + * + * @param value + * @param elementState + */ + public void markAsUnmarshalled(String value, Object elementState) + { + if (unmarshalledObjects == null) + initializeMultiMaps(); + this.unmarshalledObjects.put(value, elementState); + } + + public void resolveGraph(Object object) + { + if (visitedElements == null) + initializeMultiMaps(); + + resolveGraphRecursvie(object); + } + + /** + * + * @param elementState + */ + public void resolveGraphRecursvie(Object elementState) + { + if (SimplTypesScope.graphSwitch == GRAPH_SWITCH.ON) + { + // this.visitedElements.put(System.identityHashCode(elementState), elementState); + this.visitedElements.put(elementState.hashCode(), elementState); + + ClassDescriptor.getClassDescriptor(elementState); + + ArrayList elementFieldDescriptors = ClassDescriptor + .getClassDescriptor(elementState).elementFieldDescriptors(); + + for (FieldDescriptor elementFieldDescriptor : elementFieldDescriptors) + { + Object thatReferenceObject = null; + Field childField = elementFieldDescriptor.getField(); + try + { + thatReferenceObject = childField.get(elementState); + } + catch (IllegalAccessException e) + { + debugA("WARNING re-trying access! " + e.getStackTrace()[0]); + childField.setAccessible(true); + try + { + thatReferenceObject = childField.get(elementState); + } + catch (IllegalAccessException e1) + { + error("Can't access " + childField.getName()); + e1.printStackTrace(); + } + } + catch (Exception e) + { + System.out.println(e); + } + // ignore null reference objects + if (thatReferenceObject == null) + continue; + + FieldType childFdType = elementFieldDescriptor.getType(); + + Collection thatCollection; + switch (childFdType) + { + case COLLECTION_ELEMENT: + case COLLECTION_SCALAR: + case MAP_ELEMENT: + case MAP_SCALAR: + thatCollection = XMLTools.getCollection(thatReferenceObject); + break; + default: + thatCollection = null; + break; + } + + if (thatCollection != null && (thatCollection.size() > 0)) + { + for (Object next : thatCollection) + { + if (next instanceof Object) + { + Object compositeElement = next; + + if (this.alreadyVisited(compositeElement)) + { + // this.needsAttributeHashCode.put(System.identityHashCode(compositeElement), + // compositeElement); + this.needsAttributeHashCode.put(compositeElement.hashCode(), compositeElement); + } + else + { + this.resolveGraph(compositeElement); + } + } + } + } + else if (thatReferenceObject instanceof Object) + { + Object compositeElement = thatReferenceObject; + + if (this.alreadyVisited(compositeElement)) + { + // this.needsAttributeHashCode.put(System.identityHashCode(compositeElement), + // compositeElement); + this.needsAttributeHashCode.put(compositeElement.hashCode(), compositeElement); + } + else + { + resolveGraph(compositeElement); + } + } + } + } + } + + /** + * + * @param elementState + * @return + */ + public boolean alreadyVisited(Object elementState) + { + if (unmarshalledObjects == null) + initializeMultiMaps(); + + return this.visitedElements.contains(elementState.hashCode(), elementState) != -1; + } + + /** + * + * @param object + */ + public void mapObject(Object object) + { + if (SimplTypesScope.graphSwitch == GRAPH_SWITCH.ON) + { + if (object != null) + this.marshalledObjects.put(object.hashCode(), object); + } + } + + /** + * + * @param compositeObject + * @return + */ + public boolean alreadyMarshalled(Object compositeObject) + { + if (compositeObject == null) + return false; + + return this.marshalledObjects.contains(compositeObject.hashCode(), compositeObject) != -1; + } + + /** + * + * @param elementState + * @return + */ + public boolean needsHashCode(Object elementState) + { + return this.needsAttributeHashCode.contains(elementState.hashCode(), elementState) != -1; + } + + /** + * + * @return + */ + public boolean isGraph() + { + return this.needsAttributeHashCode.size() > 0; + } + + /** + * + * @param value + * @return + */ + public Object getFromMap(String value) + { + + return this.unmarshalledObjects.get(value); + } + + /** + * + */ + @Override + public ParsedURL purlContext() + { + return (baseDirPurl != null) ? baseDirPurl : (baseDirFile != null) ? new ParsedURL(baseDirFile) + : null; + } + + public String getSimplId(Object object) + { + Integer objectHashCode = object.hashCode(); + Integer orderedIndex = marshalledObjects.contains(objectHashCode, object); + + if (orderedIndex > 0) + return objectHashCode.toString() + "," + orderedIndex.toString(); + else + return objectHashCode.toString(); + } + + /** + * + */ + @Override + public File fileContext() + { + return (baseDirFile != null) ? baseDirFile : (baseDirPurl != null) ? baseDirPurl.file() : null; + } + + /** + * + * @return + */ + public String getDelimiter() + { + return delimiter; + } + + void clean() + { + if (marshalledObjects != null) + marshalledObjects.clear(); + if (visitedElements != null) + visitedElements.clear(); + if (needsAttributeHashCode != null) + needsAttributeHashCode.clear(); + if (needsAttributeHashCode != null) + unmarshalledObjects.clear(); + + baseDirPurl = null; + baseDirFile = null; + delimiter = ","; + } + } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/TranslationsClassProvider.java b/simplCore/src/ecologylab/serialization/TranslationsClassProvider.java index 6ccf5d9e..b21720bf 100644 --- a/simplCore/src/ecologylab/serialization/TranslationsClassProvider.java +++ b/simplCore/src/ecologylab/serialization/TranslationsClassProvider.java @@ -1,72 +1,72 @@ -/** - * - */ -package ecologylab.serialization; - -import ecologylab.generic.Debug; - -/** - * A TranslationsClassProvider is used to supply an array of Classes for a translation scope. They - * are extensible so that subclasses can provide expanded lists of Classes. - * - * To use, one instantiates the specific subclass and invokes the provideClasses() method. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public abstract class TranslationsClassProvider extends Debug -{ - private final Class[] providedClasses; - - /** - * - */ - public TranslationsClassProvider() - { - providedClasses = specificSuppliedClasses(); - } - - /** - * Subclasses must override this method to provide their specific supplied classes. Subclasses of - * subclasses should provide the combination of their own (new) class arrays and those of their - * superclass. - * - * The combineClassArrays static method is useful for this. - * - * @return - */ - protected abstract Class[] specificSuppliedClasses(); - - /** - * Convenience method for combining a number of Class arrays into a single array. - * - * @param classArray1 - * @param classArray2 - * @return - */ - protected static Class[] combineClassArrays(Class[]... classArrays) - { - int combinedArrayLength = 0; - - for (Class[] classArray : classArrays) - { - combinedArrayLength += classArray.length; - } - - Class[] returnArray = new Class[combinedArrayLength]; - - int copyPos = 0; - - for (Class[] classArray : classArrays) - { - System.arraycopy(classArray, 0, returnArray, copyPos, classArray.length); - copyPos += classArray.length; - } - - return returnArray; - } - - public final Class[] provideClasses() - { - return providedClasses; - } -} +/** + * + */ +package ecologylab.serialization; + +import ecologylab.generic.Debug; + +/** + * A TranslationsClassProvider is used to supply an array of Classes for a translation scope. They + * are extensible so that subclasses can provide expanded lists of Classes. + * + * To use, one instantiates the specific subclass and invokes the provideClasses() method. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public abstract class TranslationsClassProvider extends Debug +{ + private final Class[] providedClasses; + + /** + * + */ + public TranslationsClassProvider() + { + providedClasses = specificSuppliedClasses(); + } + + /** + * Subclasses must override this method to provide their specific supplied classes. Subclasses of + * subclasses should provide the combination of their own (new) class arrays and those of their + * superclass. + * + * The combineClassArrays static method is useful for this. + * + * @return + */ + protected abstract Class[] specificSuppliedClasses(); + + /** + * Convenience method for combining a number of Class arrays into a single array. + * + * @param classArray1 + * @param classArray2 + * @return + */ + protected static Class[] combineClassArrays(Class[]... classArrays) + { + int combinedArrayLength = 0; + + for (Class[] classArray : classArrays) + { + combinedArrayLength += classArray.length; + } + + Class[] returnArray = new Class[combinedArrayLength]; + + int copyPos = 0; + + for (Class[] classArray : classArrays) + { + System.arraycopy(classArray, 0, returnArray, copyPos, classArray.length); + copyPos += classArray.length; + } + + return returnArray; + } + + public final Class[] provideClasses() + { + return providedClasses; + } +} diff --git a/simplCore/src/ecologylab/serialization/XMLFilenameFilter.java b/simplCore/src/ecologylab/serialization/XMLFilenameFilter.java index 3867a83e..2e29a9d9 100644 --- a/simplCore/src/ecologylab/serialization/XMLFilenameFilter.java +++ b/simplCore/src/ecologylab/serialization/XMLFilenameFilter.java @@ -1,45 +1,45 @@ -/** - * - */ -package ecologylab.serialization; - -import java.io.File; -import java.io.FilenameFilter; - -/** - * A filename filter for XML files, based on their final extension. - * - * @author Zachary O. Toups (toupsz@ecologylab.net) - */ -public class XMLFilenameFilter implements FilenameFilter -{ - public final static XMLFilenameFilter staticInstance = new XMLFilenameFilter(); - - /** - * - */ - public XMLFilenameFilter() - { - } - - /** - * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String) - * - * Matches files whose final filename extension is ".xml" (case - * ignored). This will not, for example, match "foo.xml.bar", but will match - * "foo.bar.xml". - */ - @Override - public boolean accept(File dir, String name) - { - int dot = name.lastIndexOf('.'); - - if (dot == -1) - { - return false; - } - - String suffix = name.substring(dot + 1); - return "xml".equalsIgnoreCase(suffix); - } -} +/** + * + */ +package ecologylab.serialization; + +import java.io.File; +import java.io.FilenameFilter; + +/** + * A filename filter for XML files, based on their final extension. + * + * @author Zachary O. Toups (toupsz@ecologylab.net) + */ +public class XMLFilenameFilter implements FilenameFilter +{ + public final static XMLFilenameFilter staticInstance = new XMLFilenameFilter(); + + /** + * + */ + public XMLFilenameFilter() + { + } + + /** + * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String) + * + * Matches files whose final filename extension is ".xml" (case + * ignored). This will not, for example, match "foo.xml.bar", but will match + * "foo.bar.xml". + */ + @Override + public boolean accept(File dir, String name) + { + int dot = name.lastIndexOf('.'); + + if (dot == -1) + { + return false; + } + + String suffix = name.substring(dot + 1); + return "xml".equalsIgnoreCase(suffix); + } +} diff --git a/simplCore/src/ecologylab/serialization/XMLReaderPool.java b/simplCore/src/ecologylab/serialization/XMLReaderPool.java index 3aec6669..297dc760 100644 --- a/simplCore/src/ecologylab/serialization/XMLReaderPool.java +++ b/simplCore/src/ecologylab/serialization/XMLReaderPool.java @@ -1,69 +1,69 @@ -/** - * - */ -package ecologylab.serialization; - -import org.xml.sax.XMLReader; - -import ecologylab.generic.ResourcePool; - -/** - * @author toupsz - * - */ -public class XMLReaderPool extends ResourcePool -{ - - /** - * @param instantiateResourcesInPool - * @param initialPoolSize - * @param minimumPoolSize - */ - public XMLReaderPool(boolean instantiateResourcesInPool, int initialPoolSize, int minimumPoolSize) - { - super(instantiateResourcesInPool, initialPoolSize, minimumPoolSize, false); - } - - /** - * @param initialPoolSize - * @param minimumPoolSize - */ - public XMLReaderPool(int initialPoolSize, int minimumPoolSize) - { - super(initialPoolSize, minimumPoolSize); - } - - /** - * Does nothing; XMLReaders CANNOT be cleaned. - * - * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) - */ - @Override - protected void clean(XMLReader objectToClean) - { - } - - @Override - protected XMLReader generateNewResource() - { - // TODO Auto-generated method stub - return null; - } - - // /** - // * @see ecologylab.generic.ResourcePool#generateNewResource() - // */ - // @Override protected XMLReader generateNewResource() - // { - // try - // { - // return ElementStateSAXHandler.createXMLReader(); - // } - // catch (SAXException e) - // { - // e.printStackTrace(); - // } - // - // return null; - // } -} +/** + * + */ +package ecologylab.serialization; + +import org.xml.sax.XMLReader; + +import ecologylab.generic.ResourcePool; + +/** + * @author toupsz + * + */ +public class XMLReaderPool extends ResourcePool +{ + + /** + * @param instantiateResourcesInPool + * @param initialPoolSize + * @param minimumPoolSize + */ + public XMLReaderPool(boolean instantiateResourcesInPool, int initialPoolSize, int minimumPoolSize) + { + super(instantiateResourcesInPool, initialPoolSize, minimumPoolSize, false); + } + + /** + * @param initialPoolSize + * @param minimumPoolSize + */ + public XMLReaderPool(int initialPoolSize, int minimumPoolSize) + { + super(initialPoolSize, minimumPoolSize); + } + + /** + * Does nothing; XMLReaders CANNOT be cleaned. + * + * @see ecologylab.generic.ResourcePool#clean(java.lang.Object) + */ + @Override + protected void clean(XMLReader objectToClean) + { + } + + @Override + protected XMLReader generateNewResource() + { + // TODO Auto-generated method stub + return null; + } + + // /** + // * @see ecologylab.generic.ResourcePool#generateNewResource() + // */ + // @Override protected XMLReader generateNewResource() + // { + // try + // { + // return ElementStateSAXHandler.createXMLReader(); + // } + // catch (SAXException e) + // { + // e.printStackTrace(); + // } + // + // return null; + // } +} diff --git a/simplCore/src/ecologylab/serialization/XMLTools.java b/simplCore/src/ecologylab/serialization/XMLTools.java index ec3e8add..2645d5f3 100644 --- a/simplCore/src/ecologylab/serialization/XMLTools.java +++ b/simplCore/src/ecologylab/serialization/XMLTools.java @@ -1390,7 +1390,13 @@ public static void escapeXML(StringBuilder buffy, CharSequence stringToEscape) buffy.append(c); // append as char (fastest!) break; default: - if (c >= 255) + if (Character.isHighSurrogate(c)) + { + int codepoint = Character.codePointAt(stringToEscape, i); + buffy.append('&').append('#').append(codepoint).append(';'); + i++; + } + else if (c >= 255) { // println("escapeXML() ERROR: " + ((int) c)); int cInt = c; @@ -1429,7 +1435,13 @@ public static void escapeXML(Appendable appendable, CharSequence stringToEscape) appendable.append(c); // append as char (fastest!) break; default: - if (c >= 255) + if (Character.isHighSurrogate(c)) + { + int codepoint = Character.codePointAt(stringToEscape, i); + appendable.append('&').append('#').append(String.valueOf(codepoint)).append(';'); + i++; + } + else if (c >= 255) { // println("escapeXML() ERROR: " + ((int) c)); int cInt = c; diff --git a/simplCore/src/ecologylab/serialization/XMLTranslationExceptionTypes.java b/simplCore/src/ecologylab/serialization/XMLTranslationExceptionTypes.java index 10fbc7ac..51715e07 100644 --- a/simplCore/src/ecologylab/serialization/XMLTranslationExceptionTypes.java +++ b/simplCore/src/ecologylab/serialization/XMLTranslationExceptionTypes.java @@ -1,18 +1,18 @@ -package ecologylab.serialization; - -/** - * Types of exceptions that occur during operation of the translation framework. - * - * @author andruid - */ -public interface XMLTranslationExceptionTypes -{ - static final int UNKNOWN = 0; - - static final int IO_EXCEPTION = 1; - - static final int FILE_NOT_FOUND = 2; - - static final int NULL_PURL = 3; - -} +package ecologylab.serialization; + +/** + * Types of exceptions that occur during operation of the translation framework. + * + * @author andruid + */ +public interface XMLTranslationExceptionTypes +{ + static final int UNKNOWN = 0; + + static final int IO_EXCEPTION = 1; + + static final int FILE_NOT_FOUND = 2; + + static final int NULL_PURL = 3; + +} diff --git a/simplCore/src/ecologylab/serialization/annotations/DbHint.java b/simplCore/src/ecologylab/serialization/annotations/DbHint.java index 6d15a04d..190a7b07 100644 --- a/simplCore/src/ecologylab/serialization/annotations/DbHint.java +++ b/simplCore/src/ecologylab/serialization/annotations/DbHint.java @@ -1,6 +1,6 @@ -package ecologylab.serialization.annotations; - -public enum DbHint -{ - PRIMARY_KEY, NOT_NULL, NULL, UNIQUE -} +package ecologylab.serialization.annotations; + +public enum DbHint +{ + PRIMARY_KEY, NOT_NULL, NULL, UNIQUE +} diff --git a/simplCore/src/ecologylab/serialization/annotations/FieldUsage.java b/simplCore/src/ecologylab/serialization/annotations/FieldUsage.java index 2bc1e41f..c41ef0f4 100644 --- a/simplCore/src/ecologylab/serialization/annotations/FieldUsage.java +++ b/simplCore/src/ecologylab/serialization/annotations/FieldUsage.java @@ -1,20 +1,20 @@ -/** - * - */ -package ecologylab.serialization.annotations; - -/** - * Usages for SIMPL fields. - * - * @author quyin - */ -public enum FieldUsage -{ - - CODE_GENERATION, /* this field is used for code generation. */ - - SERIALIZATION_IN_STREAM, /* this field is serialized to streams (XML, JSON, ...). */ - - PERSISTENCE, /* this field is persisted in data stores. */ - -} +/** + * + */ +package ecologylab.serialization.annotations; + +/** + * Usages for SIMPL fields. + * + * @author quyin + */ +public enum FieldUsage +{ + + CODE_GENERATION, /* this field is used for code generation. */ + + SERIALIZATION_IN_STREAM, /* this field is serialized to streams (XML, JSON, ...). */ + + PERSISTENCE, /* this field is persisted in data stores. */ + +} diff --git a/simplCore/src/ecologylab/serialization/annotations/Hint.java b/simplCore/src/ecologylab/serialization/annotations/Hint.java index 81aa3801..3ef12740 100644 --- a/simplCore/src/ecologylab/serialization/annotations/Hint.java +++ b/simplCore/src/ecologylab/serialization/annotations/Hint.java @@ -1,12 +1,12 @@ -package ecologylab.serialization.annotations; - -/** - * Hints for styles when deserializing scalar fields. - * - * For instance, deserializing inner text content can be done through XML_TEXT. This can be used - * together with other scalars (attributes / leafs). - */ -public enum Hint -{ - XML_ATTRIBUTE, XML_LEAF, XML_LEAF_CDATA, XML_TEXT, XML_TEXT_CDATA, UNDEFINED, -} +package ecologylab.serialization.annotations; + +/** + * Hints for styles when deserializing scalar fields. + * + * For instance, deserializing inner text content can be done through XML_TEXT. This can be used + * together with other scalars (attributes / leafs). + */ +public enum Hint +{ + XML_ATTRIBUTE, XML_LEAF, XML_LEAF_CDATA, XML_TEXT, XML_TEXT_CDATA, UNDEFINED, +} diff --git a/simplCore/src/ecologylab/serialization/annotations/bibtex_key.java b/simplCore/src/ecologylab/serialization/annotations/bibtex_key.java index f39d8b5a..1acade77 100644 --- a/simplCore/src/ecologylab/serialization/annotations/bibtex_key.java +++ b/simplCore/src/ecologylab/serialization/annotations/bibtex_key.java @@ -1,15 +1,15 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * annotation to define the type of a bibtex key. - * - * @author nabeel - */ -@Retention(RetentionPolicy.RUNTIME) -public @interface bibtex_key -{ - -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * annotation to define the type of a bibtex key. + * + * @author nabeel + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface bibtex_key +{ + +} diff --git a/simplCore/src/ecologylab/serialization/annotations/bibtex_tag.java b/simplCore/src/ecologylab/serialization/annotations/bibtex_tag.java index 236e4719..50f64115 100644 --- a/simplCore/src/ecologylab/serialization/annotations/bibtex_tag.java +++ b/simplCore/src/ecologylab/serialization/annotations/bibtex_tag.java @@ -1,16 +1,16 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * annotation used for serializing in bibtex format. The tag value is the name of the key in - * key-value pairs of a bibtex entry - * - * @author nabeel - */ -@Retention(RetentionPolicy.RUNTIME) -public @interface bibtex_tag -{ - String value(); +package ecologylab.serialization.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * annotation used for serializing in bibtex format. The tag value is the name of the key in + * key-value pairs of a bibtex entry + * + * @author nabeel + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface bibtex_tag +{ + String value(); } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/annotations/bibtex_type.java b/simplCore/src/ecologylab/serialization/annotations/bibtex_type.java index 21b1168e..a8b05470 100644 --- a/simplCore/src/ecologylab/serialization/annotations/bibtex_type.java +++ b/simplCore/src/ecologylab/serialization/annotations/bibtex_type.java @@ -1,15 +1,15 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * annotation to define the type of a bibtex entry. - * - * @author nabeel - */ -@Retention(RetentionPolicy.RUNTIME) -public @interface bibtex_type -{ - String value(); -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * annotation to define the type of a bibtex entry. + * + * @author nabeel + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface bibtex_type +{ + String value(); +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_classes.java b/simplCore/src/ecologylab/serialization/annotations/simpl_classes.java index 5fbf0d4f..0311c69a 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_classes.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_classes.java @@ -1,20 +1,20 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Supplementary metalanguage declaration that can be applied only to a field. The argument is an - * array of Class objects. - *

- * Annotation forms tag names from each of the class names, using camel case conversion. It then - * creates a mapping from the tag and class names to the field it is applied to, so that - * translateFromXML(...) will set a value based on an element with the tags, if field is also - * declared with @xml_nested, or collect values when elements have the tags, if the field is - * declared with @xml_collection. - */ -@Retention(RetentionPolicy.RUNTIME) -public @interface simpl_classes -{ - Class[] value(); +package ecologylab.serialization.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Supplementary metalanguage declaration that can be applied only to a field. The argument is an + * array of Class objects. + *

+ * Annotation forms tag names from each of the class names, using camel case conversion. It then + * creates a mapping from the tag and class names to the field it is applied to, so that + * translateFromXML(...) will set a value based on an element with the tags, if field is also + * declared with @xml_nested, or collect values when elements have the tags, if the field is + * declared with @xml_collection. + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface simpl_classes +{ + Class[] value(); } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_collection.java b/simplCore/src/ecologylab/serialization/annotations/simpl_collection.java index 649aa08e..544f30c4 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_collection.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_collection.java @@ -1,38 +1,38 @@ - -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Metalanguage declaration that tells ecologylab.serialization translators that each Field it is - * applied to as an annotation is of type Collection. An argument may be passed to declare the tag - * name of the child elements. The XML may define any number of child elements with this tag. In - * this case, the class of the elements will be dervied from the instantiated generic type - * declaration of the children. For example, - * @xml_collection("item") ArrayList<Item> items; - *

- * For that formulation, the type of the children may be a subclass of ElementState, for full - * nested elements, or it may be a ScalarType, for leaf nodes. - *

- * Without the tag name declaration, the tag name will be derived from the class name of the - * children, and in translate from XML, the class name will be derived from the tag name, and then - * resolved in the TranslationSpace. - *

- * Alternatively, to achieve polymorphism, for children subclassed from ElementState only, this - * declaration can be combined with @xml_classes. In such cases, items of the various classes will - * be collected together in the declared Collection. Then, the tag names for these elements will - * be derived from their class declarations. - * - * @author andruid - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Inherited -public @interface simpl_collection -{ - String value() default ""; + +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Metalanguage declaration that tells ecologylab.serialization translators that each Field it is + * applied to as an annotation is of type Collection. An argument may be passed to declare the tag + * name of the child elements. The XML may define any number of child elements with this tag. In + * this case, the class of the elements will be dervied from the instantiated generic type + * declaration of the children. For example, + * @xml_collection("item") ArrayList<Item> items; + *

+ * For that formulation, the type of the children may be a subclass of ElementState, for full + * nested elements, or it may be a ScalarType, for leaf nodes. + *

+ * Without the tag name declaration, the tag name will be derived from the class name of the + * children, and in translate from XML, the class name will be derived from the tag name, and then + * resolved in the TranslationSpace. + *

+ * Alternatively, to achieve polymorphism, for children subclassed from ElementState only, this + * declaration can be combined with @xml_classes. In such cases, items of the various classes will + * be collected together in the declared Collection. Then, the tag names for these elements will + * be derived from their class declarations. + * + * @author andruid + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface simpl_collection +{ + String value() default ""; } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_composite.java b/simplCore/src/ecologylab/serialization/annotations/simpl_composite.java index 2f98db26..3f6247cf 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_composite.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_composite.java @@ -1,25 +1,25 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Metalanguage declaration that tells ecologylab.serialization translators that each Field it is - * applied to as an annotation is represented in XML by a (non-leaf) nested child element. The - * field must be a subclass of ElementState. - *

- * The nested child element name will be derived from the field name, using camel case conversion, - * unless @simpl_tag is used. - * - * @author andruid - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Inherited -public @interface simpl_composite -{ - String value() default ""; -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Metalanguage declaration that tells ecologylab.serialization translators that each Field it is + * applied to as an annotation is represented in XML by a (non-leaf) nested child element. The + * field must be a subclass of ElementState. + *

+ * The nested child element name will be derived from the field name, using camel case conversion, + * unless @simpl_tag is used. + * + * @author andruid + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface simpl_composite +{ + String value() default ""; +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_composite_as_scalar.java b/simplCore/src/ecologylab/serialization/annotations/simpl_composite_as_scalar.java index 9cc7c865..d1203d25 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_composite_as_scalar.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_composite_as_scalar.java @@ -1,15 +1,15 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * - * - * @author nabeel - */ -@Retention(RetentionPolicy.RUNTIME) -public @interface simpl_composite_as_scalar -{ - -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * + * + * @author nabeel + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface simpl_composite_as_scalar +{ + +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_db.java b/simplCore/src/ecologylab/serialization/annotations/simpl_db.java index eff3163c..383a64ed 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_db.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_db.java @@ -1,26 +1,26 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - - -/** - * Supplementary metalanguage declaration that can be applied only to a field. This is used for - * assigning database constraints to a field, which are referenced in creating correponding sql - * table schema. Database constraints are defined in 'DbHint' - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Inherited -public @interface simpl_db -{ - /** - * @return database constraints defined in 'DbHint' and name of reference table - */ - DbHint[] value(); - - String references() default "null"; -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * Supplementary metalanguage declaration that can be applied only to a field. This is used for + * assigning database constraints to a field, which are referenced in creating correponding sql + * table schema. Database constraints are defined in 'DbHint' + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface simpl_db +{ + /** + * @return database constraints defined in 'DbHint' and name of reference table + */ + DbHint[] value(); + + String references() default "null"; +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_descriptor_classes.java b/simplCore/src/ecologylab/serialization/annotations/simpl_descriptor_classes.java index ea555177..0bcbfad3 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_descriptor_classes.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_descriptor_classes.java @@ -1,23 +1,23 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Class-level annotation. - * S.IM.PL Serialization transparency. - * Enables overriding the class used for the FieldDescriptors for fields inside a particular type. - * - * @author andruid - */ - -@Inherited -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface simpl_descriptor_classes -{ - Class[] value(); -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Class-level annotation. + * S.IM.PL Serialization transparency. + * Enables overriding the class used for the FieldDescriptors for fields inside a particular type. + * + * @author andruid + */ + +@Inherited +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface simpl_descriptor_classes +{ + Class[] value(); +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_exclude_usage.java b/simplCore/src/ecologylab/serialization/annotations/simpl_exclude_usage.java index 565983ff..c5258d6b 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_exclude_usage.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_exclude_usage.java @@ -1,28 +1,28 @@ -/** - * - */ -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Used for excluding a field from certain usages. The usage of a field may affect various aspects of how it will be - * used, e.g. code generation, serialization, persistence, etc. - *

- * Note: currently, only excluding for SERIALIZATION_IN_STREAM is implemented. - * - * @author quyin - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Inherited -public @interface simpl_exclude_usage -{ - - FieldUsage[] value() default { }; - -} +/** + * + */ +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used for excluding a field from certain usages. The usage of a field may affect various aspects of how it will be + * used, e.g. code generation, serialization, persistence, etc. + *

+ * Note: currently, only excluding for SERIALIZATION_IN_STREAM is implemented. + * + * @author quyin + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface simpl_exclude_usage +{ + + FieldUsage[] value() default { }; + +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_filter.java b/simplCore/src/ecologylab/serialization/annotations/simpl_filter.java index 258155ab..25342f35 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_filter.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_filter.java @@ -1,29 +1,29 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * S.IM.PL declaration for scalar fields. - *

- * Specifies filtering a scalar value on input, using a regex, before marshalling by a ScalarType. - * Only activated when you call on your TranslationScope instance, setPerformFilters(), before - * calling deserialize(Stream). - * - * @author andruid - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Inherited -public @interface simpl_filter -{ - String regex(); - - int group() default 0; - - String replace(); +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * S.IM.PL declaration for scalar fields. + *

+ * Specifies filtering a scalar value on input, using a regex, before marshalling by a ScalarType. + * Only activated when you call on your TranslationScope instance, setPerformFilters(), before + * calling deserialize(Stream). + * + * @author andruid + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface simpl_filter +{ + String regex(); + + int group() default 0; + + String replace(); } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_format.java b/simplCore/src/ecologylab/serialization/annotations/simpl_format.java index 93f0339d..4261e7a7 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_format.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_format.java @@ -1,25 +1,25 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Optional metalanguage declaration. Enables specificaition of one or more formatting strings. - * Only affects ScalarTyped Fields (ignored otherwise). The format string will be passed to the - * ScalarType for type-specific interpretation. - *

- * An example of use is to pass DateFormat info to the DateType. - * - * @author andruid - * @author toupsz - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Inherited -public @interface simpl_format -{ - String[] value(); +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Optional metalanguage declaration. Enables specificaition of one or more formatting strings. + * Only affects ScalarTyped Fields (ignored otherwise). The format string will be passed to the + * ScalarType for type-specific interpretation. + *

+ * An example of use is to pass DateFormat info to the DateType. + * + * @author andruid + * @author toupsz + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface simpl_format +{ + String[] value(); } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_hints.java b/simplCore/src/ecologylab/serialization/annotations/simpl_hints.java index 9204821a..f466c8a0 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_hints.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_hints.java @@ -1,21 +1,21 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * S.IM.PL declaration for hints that precisely define the syntactic structure of serialization. - * - * @author andruid - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Inherited -public @interface simpl_hints -{ - Hint[] value() default - { Hint.XML_ATTRIBUTE }; -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * S.IM.PL declaration for hints that precisely define the syntactic structure of serialization. + * + * @author andruid + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface simpl_hints +{ + Hint[] value() default + { Hint.XML_ATTRIBUTE }; +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_inherit.java b/simplCore/src/ecologylab/serialization/annotations/simpl_inherit.java index fc8c4625..4a709d4e 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_inherit.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_inherit.java @@ -1,23 +1,23 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Metalanguage declaration for classes with metalanguage inside, - * which are derived from other classes that also have metalanguage that needs interpreting. - * - * @author andruid - */ - -@Inherited -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) - -public @interface simpl_inherit -{ - -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Metalanguage declaration for classes with metalanguage inside, + * which are derived from other classes that also have metalanguage that needs interpreting. + * + * @author andruid + */ + +@Inherited +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) + +public @interface simpl_inherit +{ + +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_map.java b/simplCore/src/ecologylab/serialization/annotations/simpl_map.java index b4693653..5075d5a8 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_map.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_map.java @@ -1,32 +1,32 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Metalanguage declaration that tells ecologylab.serialization translators that each Field it is - * applied to as an annotation is of type Map. An argument may be passed to declare the tag name - * of the child elements. The XML may define any number of child elements with this tag. In this - * case, the class of the elements will be dervied from the instantiated generic type declaration - * of the children. - *

- * For example, @xml_map("foo") HashMap<String, FooFoo> items;
- * The values of the Map must implement the Mappable interface, to supply a key which matches the - * key declaration in the Map's instantiated generic types. - *

- * Without the tag name declaration, the tag name will be derived from the class name of the - * children, and in translate from XML, the class name will be derived from the tag name, and then - * resolved in the TranslationSpace. - * - * @author andruid - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Inherited -public @interface simpl_map -{ - String value() default ""; -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Metalanguage declaration that tells ecologylab.serialization translators that each Field it is + * applied to as an annotation is of type Map. An argument may be passed to declare the tag name + * of the child elements. The XML may define any number of child elements with this tag. In this + * case, the class of the elements will be dervied from the instantiated generic type declaration + * of the children. + *

+ * For example, @xml_map("foo") HashMap<String, FooFoo> items;
+ * The values of the Map must implement the Mappable interface, to supply a key which matches the + * key declaration in the Map's instantiated generic types. + *

+ * Without the tag name declaration, the tag name will be derived from the class name of the + * children, and in translate from XML, the class name will be derived from the tag name, and then + * resolved in the TranslationSpace. + * + * @author andruid + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface simpl_map +{ + String value() default ""; +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_map_key_field.java b/simplCore/src/ecologylab/serialization/annotations/simpl_map_key_field.java index cab4d60c..8a963798 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_map_key_field.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_map_key_field.java @@ -1,20 +1,20 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Indicate name of the field used as key in a map. Used together with {@code @simpl_map}. - * - * @author quyin - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Inherited -public @interface simpl_map_key_field -{ - String value(); -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicate name of the field used as key in a map. Used together with {@code @simpl_map}. + * + * @author quyin + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface simpl_map_key_field +{ + String value(); +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_nowrap.java b/simplCore/src/ecologylab/serialization/annotations/simpl_nowrap.java index effab785..3b6ea695 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_nowrap.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_nowrap.java @@ -1,18 +1,18 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Used to specify that the elements of a collection or map should not be wrapped by an outer tag - * corresponding to their field name. - * - * @author andruid - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Inherited -public @interface simpl_nowrap -{ +package ecologylab.serialization.annotations; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Used to specify that the elements of a collection or map should not be wrapped by an outer tag + * corresponding to their field name. + * + * @author andruid + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface simpl_nowrap +{ } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_other_tags.java b/simplCore/src/ecologylab/serialization/annotations/simpl_other_tags.java index af7b467b..782487fe 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_other_tags.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_other_tags.java @@ -1,17 +1,17 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * This optional metalanguage declaration is used to add extra tags to a field or class, in order - * to enable backwards compatability with a previous dialect of XML. It affects only translate - * from XML; translateToXML() never uses these entries. - * - * @author andruid - */ -@Retention(RetentionPolicy.RUNTIME) -public @interface simpl_other_tags -{ - String[] value(); -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * This optional metalanguage declaration is used to add extra tags to a field or class, in order + * to enable backwards compatability with a previous dialect of XML. It affects only translate + * from XML; translateToXML() never uses these entries. + * + * @author andruid + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface simpl_other_tags +{ + String[] value(); +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_scalar.java b/simplCore/src/ecologylab/serialization/annotations/simpl_scalar.java index 24a97a5b..0daa47f7 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_scalar.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_scalar.java @@ -1,23 +1,23 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Metalanguage declaration that tells simpl serialization that each Field it is applied to as an - * annotation is a scalar-value. - *

- * The attribute name will be derived from the field name, using camel case conversion, unless @simpl_tag - * is used. - * - * @author andruid - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -@Inherited -public @interface simpl_scalar -{ +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Metalanguage declaration that tells simpl serialization that each Field it is applied to as an + * annotation is a scalar-value. + *

+ * The attribute name will be derived from the field name, using camel case conversion, unless @simpl_tag + * is used. + * + * @author andruid + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Inherited +public @interface simpl_scalar +{ } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_scope.java b/simplCore/src/ecologylab/serialization/annotations/simpl_scope.java index 611f7cec..afe36878 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_scope.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_scope.java @@ -1,23 +1,23 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Supplementary metalanguage declaration that can be applied only to a field. The argument is the - * name of a TranslationScope. - *

- * Annotation uses the argument to lookup a TranslationScope. If there is none, a warning is - * provided. Otherwise, mappings are created for tag names associated with each class in the - * TranslationScope. It then creates a mapping from the tag and class names to the field it is - * applied to, so that translateFromXML(...) will set a value based on an element with the tags, - * if field is also declared with @xml_nested, or collect values when elements have the tags, if - * the field is declared with @xml_collection. - */ -@Retention(RetentionPolicy.RUNTIME) -@Inherited -public @interface simpl_scope -{ - String value(); -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Supplementary metalanguage declaration that can be applied only to a field. The argument is the + * name of a TranslationScope. + *

+ * Annotation uses the argument to lookup a TranslationScope. If there is none, a warning is + * provided. Otherwise, mappings are created for tag names associated with each class in the + * TranslationScope. It then creates a mapping from the tag and class names to the field it is + * applied to, so that translateFromXML(...) will set a value based on an element with the tags, + * if field is also declared with @xml_nested, or collect values when elements have the tags, if + * the field is declared with @xml_collection. + */ +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface simpl_scope +{ + String value(); +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_tag.java b/simplCore/src/ecologylab/serialization/annotations/simpl_tag.java index 7abca96b..d6c845a2 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_tag.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_tag.java @@ -1,33 +1,33 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Metalanguage declaration that can be applied either to field or to class declarations. - * - * Annotation that tells ecologylab.serialization translators that instead of generating a name - * for XML elements corresponding to the field or class using camel case conversion, one is - * specified explicitly. This name is specified by the value of this annotation. - *

- * Note that programmers should be careful when specifying an xml_tag, to ensure that there are no - * collisions with other names. Note that when an xml_tag is specified for a field or class, it - * will ALWAYS EMIT AND TRANSLATE FROM USING THAT NAME. - * - * xml_tag's should typically be something that cannot be represented using camel case name - * conversion, such as utilizing characters that are not normally allowed in field names, but that - * are allowed in XML names. This can be particularly useful for building ElementState objects out - * of XML from the wild. - *

- * You cannot use XML-forbidden characters or constructs in an xml_tag! - * - * When using @simpl_tag, you MUST create your corresponding TranslationSpace entry using a Class - * object, instead of using a default package name. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -@Retention(RetentionPolicy.RUNTIME) -public @interface simpl_tag -{ - String value(); -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Metalanguage declaration that can be applied either to field or to class declarations. + * + * Annotation that tells ecologylab.serialization translators that instead of generating a name + * for XML elements corresponding to the field or class using camel case conversion, one is + * specified explicitly. This name is specified by the value of this annotation. + *

+ * Note that programmers should be careful when specifying an xml_tag, to ensure that there are no + * collisions with other names. Note that when an xml_tag is specified for a field or class, it + * will ALWAYS EMIT AND TRANSLATE FROM USING THAT NAME. + * + * xml_tag's should typically be something that cannot be represented using camel case name + * conversion, such as utilizing characters that are not normally allowed in field names, but that + * are allowed in XML names. This can be particularly useful for building ElementState objects out + * of XML from the wild. + *

+ * You cannot use XML-forbidden characters or constructs in an xml_tag! + * + * When using @simpl_tag, you MUST create your corresponding TranslationSpace entry using a Class + * object, instead of using a default package name. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface simpl_tag +{ + String value(); +} diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_use_equals_equals.java b/simplCore/src/ecologylab/serialization/annotations/simpl_use_equals_equals.java index a31bec73..5e44f05f 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_use_equals_equals.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_use_equals_equals.java @@ -1,23 +1,23 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * This annotation specifices that the == test (not .equals) will be used during de/serialization - * to detect equivalent objects - * - * @author sumith - */ - -@Inherited -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) - -public @interface simpl_use_equals_equals -{ - +package ecologylab.serialization.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation specifices that the == test (not .equals) will be used during de/serialization + * to detect equivalent objects + * + * @author sumith + */ + +@Inherited +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) + +public @interface simpl_use_equals_equals +{ + } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/annotations/simpl_wrap.java b/simplCore/src/ecologylab/serialization/annotations/simpl_wrap.java index 13ea0b9a..a4cdf3dd 100644 --- a/simplCore/src/ecologylab/serialization/annotations/simpl_wrap.java +++ b/simplCore/src/ecologylab/serialization/annotations/simpl_wrap.java @@ -1,18 +1,18 @@ -package ecologylab.serialization.annotations; - -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Used to specify that the elements of a collection or map should be wrapped by an outer tag - * corresponding to their field name. - * - * @author andruid - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Inherited -public @interface simpl_wrap -{ -} +package ecologylab.serialization.annotations; + +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Used to specify that the elements of a collection or map should be wrapped by an outer tag + * corresponding to their field name. + * + * @author andruid + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface simpl_wrap +{ +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/ISimplDeserializationIn.java b/simplCore/src/ecologylab/serialization/deserializers/ISimplDeserializationIn.java index 0d6fd5c8..6859dc7a 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/ISimplDeserializationIn.java +++ b/simplCore/src/ecologylab/serialization/deserializers/ISimplDeserializationIn.java @@ -1,8 +1,8 @@ -package ecologylab.serialization.deserializers; - -import ecologylab.serialization.TranslationContext; - -public interface ISimplDeserializationIn -{ - void deserializationInHook(TranslationContext translationContext); -} +package ecologylab.serialization.deserializers; + +import ecologylab.serialization.TranslationContext; + +public interface ISimplDeserializationIn +{ + void deserializationInHook(TranslationContext translationContext); +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/ISimplDeserializationPost.java b/simplCore/src/ecologylab/serialization/deserializers/ISimplDeserializationPost.java index 213d5d7b..5494a0fd 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/ISimplDeserializationPost.java +++ b/simplCore/src/ecologylab/serialization/deserializers/ISimplDeserializationPost.java @@ -1,8 +1,8 @@ -package ecologylab.serialization.deserializers; - -import ecologylab.serialization.TranslationContext; - -public interface ISimplDeserializationPost -{ - void deserializationPostHook(TranslationContext translationContext, Object object); -} +package ecologylab.serialization.deserializers; + +import ecologylab.serialization.TranslationContext; + +public interface ISimplDeserializationPost +{ + void deserializationPostHook(TranslationContext translationContext, Object object); +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/ISimplDeserializationPre.java b/simplCore/src/ecologylab/serialization/deserializers/ISimplDeserializationPre.java index 9ae4bcf8..4b14819f 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/ISimplDeserializationPre.java +++ b/simplCore/src/ecologylab/serialization/deserializers/ISimplDeserializationPre.java @@ -1,8 +1,8 @@ -package ecologylab.serialization.deserializers; - -import ecologylab.serialization.TranslationContext; - -public interface ISimplDeserializationPre -{ - void deserializationPreHook(TranslationContext translationContext); -} +package ecologylab.serialization.deserializers; + +import ecologylab.serialization.TranslationContext; + +public interface ISimplDeserializationPre +{ + void deserializationPreHook(TranslationContext translationContext); +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/parsers/tlv/TLVEvents.java b/simplCore/src/ecologylab/serialization/deserializers/parsers/tlv/TLVEvents.java index b6857e46..b63339a1 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/parsers/tlv/TLVEvents.java +++ b/simplCore/src/ecologylab/serialization/deserializers/parsers/tlv/TLVEvents.java @@ -1,20 +1,20 @@ -package ecologylab.serialization.deserializers.parsers.tlv; - -/** - * Interface which can be implemented by the class handling parsing of tlv messages. - * - * @author Nabeel Shahzad - * - */ -public interface TLVEvents -{ - public void startTLV(); - - public void startObject(String objectName); - - public void endObject(String objectName); - - public void primitive(String value); - - public void endTLV(); -} +package ecologylab.serialization.deserializers.parsers.tlv; + +/** + * Interface which can be implemented by the class handling parsing of tlv messages. + * + * @author Nabeel Shahzad + * + */ +public interface TLVEvents +{ + public void startTLV(); + + public void startObject(String objectName); + + public void endObject(String objectName); + + public void primitive(String value); + + public void endTLV(); +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/parsers/tlv/TLVParser.java b/simplCore/src/ecologylab/serialization/deserializers/parsers/tlv/TLVParser.java index 55358313..8bdd77fc 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/parsers/tlv/TLVParser.java +++ b/simplCore/src/ecologylab/serialization/deserializers/parsers/tlv/TLVParser.java @@ -1,166 +1,166 @@ -package ecologylab.serialization.deserializers.parsers.tlv; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.FieldType; -import ecologylab.serialization.FieldTypes; -import ecologylab.serialization.SimplTypesScope; - -/** - * This is the basic tlv parser for parsing tlv messages generated from - * ecologylab.serialization translation framework. - * - *

- * The framework works in conjunction with the translation scope to map tlv ids with their tag - * names. TLV messages are type-length-value triplet. type is a 32 bit integer takes up - * to 4 bytes. length is also a 32 bit integer and takes up to 4 bytes of the message - * header of the tlv message. - * - * - * - * @author Nabeel Shahzad - * - * @version 1.0 - */ -public class TLVParser implements FieldTypes -{ - /** - * an object which implements TLVEvents will get the appropriate events from the parser. - */ - private TLVEvents listenerObject; - - /** - * translation scope which maps tlv ids to tag names. - */ - private SimplTypesScope translationScope; - - /** - * local state variable. - */ - private ClassDescriptor currentClassDescriptor; - - /** - * constant for type field size. - */ - final int TYPE_SIZE = 4; - - /** - * constant for length field size - */ - final int LENGTH_SIZE = 4; - - /** - * contant for header size. - */ - final int HEADER_SIZE = TYPE_SIZE + LENGTH_SIZE; - - /** - * Constructor for tlv parser. - * - * @param listenerObject - * @param translationScope - */ - public TLVParser(TLVEvents listenerObject, SimplTypesScope translationScope) - { - this.listenerObject = listenerObject; - this.translationScope = translationScope; - } - - /** - * Parse method that creates an element state object which wraps whole message - * - * @param dataArray - */ - public void parse(byte[] dataArray) - { - // Start event for TLV data. - listenerObject.startTLV(); - - int type = Utils.getInt(dataArray, 0); - int length = Utils.getInt(dataArray, 4); - - currentClassDescriptor = translationScope.getClassDescriptorByTLVId(type); - - String rootObjectName = currentClassDescriptor.getTagName(); - - // start of first object. - listenerObject.startObject(rootObjectName); - - parseTLVBlock(dataArray, HEADER_SIZE, length, currentClassDescriptor.pseudoFieldDescriptor()); - - // end of first object . - listenerObject.endObject(rootObjectName); - - // End event for TLV data - listenerObject.endTLV(); - } - - /** - * Method which recursively looks down for tlv blocks and parses them also calls methods on the - * TLVEvents interface. - * - * @param dataArray - * @param start - * @param offset - * @param currentFieldDescriptor - */ - public void parseTLVBlock(byte[] dataArray, int start, int offset, - FieldDescriptor currentFieldDescriptor) - { - try - { - int type = Utils.getInt(dataArray, start); - int length = Utils.getInt(dataArray, start + 4); - FieldDescriptor localCurrentFieldDescriptor = currentFieldDescriptor; - boolean isScalar = false; - - FieldType currentType = currentFieldDescriptor.getType(); - - currentFieldDescriptor = (currentType == FieldType.WRAPPER) ? currentFieldDescriptor.getWrappedFD() - : currentClassDescriptor.getFieldDescriptorByTLVId(type); - - //if(currentFieldDescriptor.isPolymorphic()) currentFieldDescriptor = currentFieldDescriptor.elementClassDescriptor(type).pseudoFieldDescriptor(); - - String currentObjectName = currentFieldDescriptor.elementName(type); - - listenerObject.startObject(currentObjectName); - - isScalar = currentFieldDescriptor.isScalar(); - - if (!isScalar) - { - if (currentFieldDescriptor.getType() == FieldType.COMPOSITE_ELEMENT - || currentFieldDescriptor.getType() == FieldType.COLLECTION_ELEMENT - || currentFieldDescriptor.getType() == FieldType.MAP_ELEMENT) - { - currentClassDescriptor = currentFieldDescriptor.elementClassDescriptor(type); - } - - // if its not scalar then there is another tlv block ahead - parseTLVBlock(dataArray, start + HEADER_SIZE, length, currentFieldDescriptor); - } - else - { - String value = new String(dataArray, start + HEADER_SIZE, length); - listenerObject.primitive(value); - } - - listenerObject.endObject(currentObjectName); - - // restore parsing states for more tlv blocks - currentClassDescriptor = currentFieldDescriptor.getDeclaringClassDescriptor(); - currentFieldDescriptor = localCurrentFieldDescriptor; - - int tlvBlockSize = HEADER_SIZE + length; - - // if there are more TLV blocks parse them - if (tlvBlockSize < offset) - parseTLVBlock(dataArray, start + tlvBlockSize, offset - tlvBlockSize, - currentFieldDescriptor); - } - catch (Exception ex) - { - ex.printStackTrace(); - } - } -} +package ecologylab.serialization.deserializers.parsers.tlv; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.FieldType; +import ecologylab.serialization.FieldTypes; +import ecologylab.serialization.SimplTypesScope; + +/** + * This is the basic tlv parser for parsing tlv messages generated from + * ecologylab.serialization translation framework. + * + *

+ * The framework works in conjunction with the translation scope to map tlv ids with their tag + * names. TLV messages are type-length-value triplet. type is a 32 bit integer takes up + * to 4 bytes. length is also a 32 bit integer and takes up to 4 bytes of the message + * header of the tlv message. + * + * + * + * @author Nabeel Shahzad + * + * @version 1.0 + */ +public class TLVParser implements FieldTypes +{ + /** + * an object which implements TLVEvents will get the appropriate events from the parser. + */ + private TLVEvents listenerObject; + + /** + * translation scope which maps tlv ids to tag names. + */ + private SimplTypesScope translationScope; + + /** + * local state variable. + */ + private ClassDescriptor currentClassDescriptor; + + /** + * constant for type field size. + */ + final int TYPE_SIZE = 4; + + /** + * constant for length field size + */ + final int LENGTH_SIZE = 4; + + /** + * contant for header size. + */ + final int HEADER_SIZE = TYPE_SIZE + LENGTH_SIZE; + + /** + * Constructor for tlv parser. + * + * @param listenerObject + * @param translationScope + */ + public TLVParser(TLVEvents listenerObject, SimplTypesScope translationScope) + { + this.listenerObject = listenerObject; + this.translationScope = translationScope; + } + + /** + * Parse method that creates an element state object which wraps whole message + * + * @param dataArray + */ + public void parse(byte[] dataArray) + { + // Start event for TLV data. + listenerObject.startTLV(); + + int type = Utils.getInt(dataArray, 0); + int length = Utils.getInt(dataArray, 4); + + currentClassDescriptor = translationScope.getClassDescriptorByTLVId(type); + + String rootObjectName = currentClassDescriptor.getTagName(); + + // start of first object. + listenerObject.startObject(rootObjectName); + + parseTLVBlock(dataArray, HEADER_SIZE, length, currentClassDescriptor.pseudoFieldDescriptor()); + + // end of first object . + listenerObject.endObject(rootObjectName); + + // End event for TLV data + listenerObject.endTLV(); + } + + /** + * Method which recursively looks down for tlv blocks and parses them also calls methods on the + * TLVEvents interface. + * + * @param dataArray + * @param start + * @param offset + * @param currentFieldDescriptor + */ + public void parseTLVBlock(byte[] dataArray, int start, int offset, + FieldDescriptor currentFieldDescriptor) + { + try + { + int type = Utils.getInt(dataArray, start); + int length = Utils.getInt(dataArray, start + 4); + FieldDescriptor localCurrentFieldDescriptor = currentFieldDescriptor; + boolean isScalar = false; + + FieldType currentType = currentFieldDescriptor.getType(); + + currentFieldDescriptor = (currentType == FieldType.WRAPPER) ? currentFieldDescriptor.getWrappedFD() + : currentClassDescriptor.getFieldDescriptorByTLVId(type); + + //if(currentFieldDescriptor.isPolymorphic()) currentFieldDescriptor = currentFieldDescriptor.elementClassDescriptor(type).pseudoFieldDescriptor(); + + String currentObjectName = currentFieldDescriptor.elementName(type); + + listenerObject.startObject(currentObjectName); + + isScalar = currentFieldDescriptor.isScalar(); + + if (!isScalar) + { + if (currentFieldDescriptor.getType() == FieldType.COMPOSITE_ELEMENT + || currentFieldDescriptor.getType() == FieldType.COLLECTION_ELEMENT + || currentFieldDescriptor.getType() == FieldType.MAP_ELEMENT) + { + currentClassDescriptor = currentFieldDescriptor.elementClassDescriptor(type); + } + + // if its not scalar then there is another tlv block ahead + parseTLVBlock(dataArray, start + HEADER_SIZE, length, currentFieldDescriptor); + } + else + { + String value = new String(dataArray, start + HEADER_SIZE, length); + listenerObject.primitive(value); + } + + listenerObject.endObject(currentObjectName); + + // restore parsing states for more tlv blocks + currentClassDescriptor = currentFieldDescriptor.getDeclaringClassDescriptor(); + currentFieldDescriptor = localCurrentFieldDescriptor; + + int tlvBlockSize = HEADER_SIZE + length; + + // if there are more TLV blocks parse them + if (tlvBlockSize < offset) + parseTLVBlock(dataArray, start + tlvBlockSize, offset - tlvBlockSize, + currentFieldDescriptor); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/parsers/tlv/Utils.java b/simplCore/src/ecologylab/serialization/deserializers/parsers/tlv/Utils.java index 691719af..c35ca82a 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/parsers/tlv/Utils.java +++ b/simplCore/src/ecologylab/serialization/deserializers/parsers/tlv/Utils.java @@ -1,538 +1,538 @@ -package ecologylab.serialization.deserializers.parsers.tlv; - -/* - * - * - * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 only, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is - * included at /legal/license.txt). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this work; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa - * Clara, CA 95054 or visit www.sun.com if you need additional - * information or have any questions. - */ - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; -import java.util.Calendar; - -/** - * This class implements miscellaneous utility methods including - * those used for conversion of BigIntegers to - * byte arrays, hexadecimal printing of byte arrays etc. - */ -public class Utils { - - /** UTF-8 encoding name. */ - public static final String utf8 = "UTF-8"; - - /** Hexadecimal digits. */ - private static char[] hc = { '0', '1', '2', '3', '4', '5', '6', - '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - - /** - * Returns hex value for given sequence of bytes. - * @param b source data - * @param off offset of the first byte - * @param len length of the value - * @return hex value for given sequence of bytes. - */ - public static String hexNumber(byte[] b, int off, int len) { - - char[] r; - int v; - int i; - int j; - - if ((b == null) || (len == 0)) { - return ""; - } - - if ((off < 0) || (len < 0)) { - throw new ArrayIndexOutOfBoundsException(); - } - - r = new char[len * 2]; - - for (i = 0, j = 0;;) { - v = b[off + i] & 0xff; - r[j++] = hc[v >>> 4]; - r[j++] = hc[v & 0x0f]; - - i++; - if (i >= len) { - break; - } - } - - return (new String(r, 0, j)); - } - - /** - * Returns hex value for given byte. - * @param b source data - * @return hex value. - */ - public static String hexByte(int b) { - b = b & 0xff; - return new String(new char[] { hc[b >>> 4], hc[b & 0x0f] }); - } - - /** - * Checks if two byte arrays match. - * @param a the first byte array - * @param aOff starting offset for comparison within a - * @param aLen length of data in the first array - * @param b the second byte array - * @param bOff starting offset for comparison within b - * @param bLen length of data in the second array - * @return true if the sequence of len bytes in a starting at - * aOff matches those in b starting at bOff, false otherwise - */ - public static boolean byteMatch(byte[] a, int aOff, int aLen, - byte[] b, int bOff, int bLen) { - if ((aLen != bLen) || (a.length < aOff + aLen) - || (b.length < bOff + bLen)) { - return false; - } - - for (int i = 0; i < aLen; i++) { - if (a[i + aOff] != b[i + bOff]) - return false; - } - - return true; - } - - /** - * Checks if two byte arrays match. - * @param a the first byte array - * @param b the second byte array - * @return true if both arrays has the same length and contents - */ - public static boolean byteMatch(byte[] a, byte[] b) { - return byteMatch(a, 0, a.length, b, 0, b.length); - } - - /** - * Converts a sequence of bytes into a printable OID, - * a string of decimal digits, each separated by a ".". - * @param buffer byte array containing the bytes to be converted - * @param offset starting offset of the byte subsequence inside b - * @param length number of bytes to be converted - * @return printable OID - */ - public static String OIDtoString(byte[] buffer, int offset, - int length) { - - StringBuffer result; - int end; - int t; - int x; - int y; - - if (length == 0) { - return ""; - } - - result = new StringBuffer(40); - - end = offset + length; - - // first byte (t) always represents the first 2 values (x, y). - // t = (x * 40) + y; - - t = buffer[offset++] & 0xff; - x = t / 40; - y = t - (x * 40); - - result.append(x); - result.append('.'); - result.append(y); - - x = 0; - while (offset < end) { - // 7 bit per byte, bit 8 = 0 means the end of a value - x = x << 7; - - t = buffer[offset++]; - if (t >= 0) { - x += t; - result.append('.'); - result.append(x); - x = 0; - } else { - x += t & 0x7f; - } - } - - return result.toString(); - } - - /** - * Converst OID from string representation into byte array. - * @param oid string representation of OID - * @return byte array containing DER value for this OID. - */ - public static byte[] StringToOID(String oid) { - - if (oid.indexOf('-') != -1) { - throw new IllegalArgumentException(oid); - } - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - int i = 0; - int b1 = 0; - int current = 0; - - while (current < oid.length()) { - - i++; - - int k = oid.indexOf('.', current); - if (k == -1) { - k = oid.length(); - } - - int v = Integer.parseInt(oid.substring(current, k)); - current = k + 1; - - if (i == 1) { - b1 = v; - continue; - } - - if (i == 2) { - v = b1 * 40 + v; - if (v > 255) { - throw new IllegalArgumentException(oid); - } - out.write(v); - continue; - } - - int p = 0; - k = v; - - while (true) { - p += 1; - k = k >> 7; - if (k == 0) { - break; - } - } - - k = v; - while (p > 0) { - - byte x = (byte) (k >> ((p - 1) * 7)); - - if (p == 1) { - x &= 0x7f; - } else { - x |= 0x80; - } - p--; - out.write(x); - } - } - - if (i < 2) { - throw new IllegalArgumentException(oid); - } - - return out.toByteArray(); - } - - /** - * Retrieves short value from byte array. - * @param data byte array - * @param offset value offset - * @return the short value - */ - public static short getShort(byte[] data, int offset) { - return (short) getU2(data, offset); - } - - /** - * Retrieves unsigned 2-byte value from byte array. - * @param data byte array - * @param offset value offset - * @return the value - */ - public static int getU2(byte[] data, int offset) { - return ((data[offset] & 0xff) << 8) | (data[offset + 1] & 0xff); - } - - /** - * Constructs integer value from byte array data. - * @param data the byte array. - * @param offset offset of the data. - * @return the integer value. - */ - public static int getInt(byte[] data, int offset) { - - int l = 0; - for (int k = 0; k < 4; k++) { - l = (l << 8) | (data[offset++] & 0xFF); - } - return l; - } - - /** - * Calculates SHA-1 hash for given data. - * @param inBuf array containing the data - * @param inOff data offset - * @param inLen data length - * @return SHA-1 hash - */ - public static byte[] getHash(byte[] inBuf, int inOff, int inLen) { - - try { - MessageDigest sha = MessageDigest.getInstance("SHA"); - sha.reset(); - byte[] hash = new byte[20]; - hash = sha.digest(inBuf); - return hash; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - /** - * Returns byte array which contains encoded short value. - * @param i the value - * @return byte array - */ - public static byte[] shortToBytes(int i) { - - byte[] data = new byte[2]; - data[0] = (byte) (i >> 8); - data[1] = (byte) i; - return data; - } - - /** - * Returns byte array that contains sequence of encoded short values. - * @param data the short values - * @return byte array - */ - - public static byte[] shortsToBytes(short[] data) { - - byte[] d = new byte[2 * data.length]; - for (int i = 0; i < data.length; i++) { - d[i * 2] = (byte) (data[i] >> 8); - d[i * 2 + 1] = (byte) data[i]; - } - return d; - } - - /** - * Returns UTF 8 encoding for this string. - * @param s the string - * @return UTF 8 encoding - */ - public static byte[] stringToBytes(String s) { - try { - return s.getBytes(utf8); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - - System.out.println("Internal error: unsupported encoding"); - return null; - } - - /** - * Converts the calender to a string. - * @param calendar input date information - * @return formatted calendar string - */ - public static String calendarToString(Calendar calendar) { - String[] months = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - - String[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", - "Sat" }; - - if (calendar == null) { - return "Thu Jan 01 00:00:00 UTC 1970"; - } - - int dow = calendar.get(Calendar.DAY_OF_WEEK); - int month = calendar.get(Calendar.MONTH); - int day = calendar.get(Calendar.DAY_OF_MONTH); - int hour_of_day = calendar.get(Calendar.HOUR_OF_DAY); - int minute = calendar.get(Calendar.MINUTE); - int seconds = calendar.get(Calendar.SECOND); - int year = calendar.get(Calendar.YEAR); - - String yr = Integer.toString(year); - - // TimeZone zone = calendar.getTimeZone(); - // String zoneID = zone.getID(); - // if (zoneID == null) zoneID = ""; - String zoneID = "GMT"; - - // The total size of the string buffer - // 3+1+3+1+2+1+2+1+2+1+2+1+zoneID.length+1+yr.length - // = 21 + zoneID.length + yr.length - StringBuffer sb = new StringBuffer(25 + zoneID.length() - + yr.length()); - - sb.append(days[dow - 1]).append(' '); - sb.append(months[month]).append(' '); - appendTwoDigits(sb, day).append(' '); - appendTwoDigits(sb, hour_of_day).append(':'); - appendTwoDigits(sb, minute).append(':'); - appendTwoDigits(sb, seconds).append(' '); - if (zoneID.length() > 0) - sb.append(zoneID).append(' '); - appendFourDigits(sb, year); - - return sb.toString(); - } - - /** - * Appends zero filled numeric string for two digit numbers. - * @param sb current formatted buffer - * @param number the digit to format - * @return updated formatted string buffer - */ - private static final StringBuffer appendTwoDigits(StringBuffer sb, - int number) { - if (number < 10) { - sb.append('0'); - } - return sb.append(number); - } - - /** - * Appends zero filled numeric string for four digit numbers. - * @param sb current formatted buffer - * @param number the digit to format - * @return updated formatted string buffer - */ - private static final StringBuffer appendFourDigits(StringBuffer sb, - int number) { - if (number >= 0 && number < 1000) { - sb.append('0'); - if (number < 100) { - sb.append('0'); - } - if (number < 10) { - sb.append('0'); - } - } - return sb.append(number); - } - - /** - * Writes hex representation of byte array elements. - * @param writer where to write - * @param data data to be written - */ - public static void writeHex(PrintStream writer, byte[] data) { - - String s = ""; - - for (int i = 0; i < data.length; i++) { - - if (data[i] > -1 && data[i] < 16) { - s = s + "0"; - } - s = s + Integer.toHexString(data[i] & 0xff) + " "; - - if ((i + 1) % 16 == 0) { - writer.println(s); - s = ""; - } - } - - if (s.length() != 4) { - writer.println(s); - } - } - - /** - * Converts string to array of shorts - * @param str input string - * @return output array of shorts - */ - public static short[] stringToShorts(String str) { - byte[] b = str.getBytes(); - short[] res = new short[1 + (b.length / 4)]; - for (int i = 0; i < b.length; i++) { - if ((b[i] >= 0x30) & (b[i] <= 0x39)) { - b[i] = (byte) (b[i] - 0x30); - } else { - if ((b[i] >= 0x41) & (b[i] <= 0x46)) { - b[i] = (byte) (b[i] - 0x41 + 0xa); - } else { - if ((b[i] >= 0x61) & (b[i] <= 0x66)) { - b[i] = (byte) (b[i] - 0x61 + 0xa); - } - } - - } - } - res[0] = 0x3fff; - for (int i = 0; i < res.length - 1; i++) { - res[i + 1] = (short) ((b[4 * i] << 12) - | (b[4 * i + 1] << 8) | (b[4 * i + 2] << 4) | b[4 * i + 3]); - } - return res; - } - - /** - * Creates java source for static array initialization. - * @param writer where to write - * @param name array name - * @param data initial values - */ - public static void writeDataArray(PrintStream writer, String name, - byte[] data) { - - writer.println(); - - String s = " static byte[] " + name + " = { "; - - for (int i = 0; i < data.length; i++) { - - if (i != 0) { - s = s + ", "; - } - - String h = "" + data[i]; - - if (s.length() + h.length() > 76) { - writer.println(s); - s = " "; - } - - s = s + h; - } - - writer.println(s + "};"); - writer.println(); - } +package ecologylab.serialization.deserializers.parsers.tlv; + +/* + * + * + * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 only, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is + * included at /legal/license.txt). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this work; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa + * Clara, CA 95054 or visit www.sun.com if you need additional + * information or have any questions. + */ + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.util.Calendar; + +/** + * This class implements miscellaneous utility methods including + * those used for conversion of BigIntegers to + * byte arrays, hexadecimal printing of byte arrays etc. + */ +public class Utils { + + /** UTF-8 encoding name. */ + public static final String utf8 = "UTF-8"; + + /** Hexadecimal digits. */ + private static char[] hc = { '0', '1', '2', '3', '4', '5', '6', + '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + /** + * Returns hex value for given sequence of bytes. + * @param b source data + * @param off offset of the first byte + * @param len length of the value + * @return hex value for given sequence of bytes. + */ + public static String hexNumber(byte[] b, int off, int len) { + + char[] r; + int v; + int i; + int j; + + if ((b == null) || (len == 0)) { + return ""; + } + + if ((off < 0) || (len < 0)) { + throw new ArrayIndexOutOfBoundsException(); + } + + r = new char[len * 2]; + + for (i = 0, j = 0;;) { + v = b[off + i] & 0xff; + r[j++] = hc[v >>> 4]; + r[j++] = hc[v & 0x0f]; + + i++; + if (i >= len) { + break; + } + } + + return (new String(r, 0, j)); + } + + /** + * Returns hex value for given byte. + * @param b source data + * @return hex value. + */ + public static String hexByte(int b) { + b = b & 0xff; + return new String(new char[] { hc[b >>> 4], hc[b & 0x0f] }); + } + + /** + * Checks if two byte arrays match. + * @param a the first byte array + * @param aOff starting offset for comparison within a + * @param aLen length of data in the first array + * @param b the second byte array + * @param bOff starting offset for comparison within b + * @param bLen length of data in the second array + * @return true if the sequence of len bytes in a starting at + * aOff matches those in b starting at bOff, false otherwise + */ + public static boolean byteMatch(byte[] a, int aOff, int aLen, + byte[] b, int bOff, int bLen) { + if ((aLen != bLen) || (a.length < aOff + aLen) + || (b.length < bOff + bLen)) { + return false; + } + + for (int i = 0; i < aLen; i++) { + if (a[i + aOff] != b[i + bOff]) + return false; + } + + return true; + } + + /** + * Checks if two byte arrays match. + * @param a the first byte array + * @param b the second byte array + * @return true if both arrays has the same length and contents + */ + public static boolean byteMatch(byte[] a, byte[] b) { + return byteMatch(a, 0, a.length, b, 0, b.length); + } + + /** + * Converts a sequence of bytes into a printable OID, + * a string of decimal digits, each separated by a ".". + * @param buffer byte array containing the bytes to be converted + * @param offset starting offset of the byte subsequence inside b + * @param length number of bytes to be converted + * @return printable OID + */ + public static String OIDtoString(byte[] buffer, int offset, + int length) { + + StringBuffer result; + int end; + int t; + int x; + int y; + + if (length == 0) { + return ""; + } + + result = new StringBuffer(40); + + end = offset + length; + + // first byte (t) always represents the first 2 values (x, y). + // t = (x * 40) + y; + + t = buffer[offset++] & 0xff; + x = t / 40; + y = t - (x * 40); + + result.append(x); + result.append('.'); + result.append(y); + + x = 0; + while (offset < end) { + // 7 bit per byte, bit 8 = 0 means the end of a value + x = x << 7; + + t = buffer[offset++]; + if (t >= 0) { + x += t; + result.append('.'); + result.append(x); + x = 0; + } else { + x += t & 0x7f; + } + } + + return result.toString(); + } + + /** + * Converst OID from string representation into byte array. + * @param oid string representation of OID + * @return byte array containing DER value for this OID. + */ + public static byte[] StringToOID(String oid) { + + if (oid.indexOf('-') != -1) { + throw new IllegalArgumentException(oid); + } + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + int i = 0; + int b1 = 0; + int current = 0; + + while (current < oid.length()) { + + i++; + + int k = oid.indexOf('.', current); + if (k == -1) { + k = oid.length(); + } + + int v = Integer.parseInt(oid.substring(current, k)); + current = k + 1; + + if (i == 1) { + b1 = v; + continue; + } + + if (i == 2) { + v = b1 * 40 + v; + if (v > 255) { + throw new IllegalArgumentException(oid); + } + out.write(v); + continue; + } + + int p = 0; + k = v; + + while (true) { + p += 1; + k = k >> 7; + if (k == 0) { + break; + } + } + + k = v; + while (p > 0) { + + byte x = (byte) (k >> ((p - 1) * 7)); + + if (p == 1) { + x &= 0x7f; + } else { + x |= 0x80; + } + p--; + out.write(x); + } + } + + if (i < 2) { + throw new IllegalArgumentException(oid); + } + + return out.toByteArray(); + } + + /** + * Retrieves short value from byte array. + * @param data byte array + * @param offset value offset + * @return the short value + */ + public static short getShort(byte[] data, int offset) { + return (short) getU2(data, offset); + } + + /** + * Retrieves unsigned 2-byte value from byte array. + * @param data byte array + * @param offset value offset + * @return the value + */ + public static int getU2(byte[] data, int offset) { + return ((data[offset] & 0xff) << 8) | (data[offset + 1] & 0xff); + } + + /** + * Constructs integer value from byte array data. + * @param data the byte array. + * @param offset offset of the data. + * @return the integer value. + */ + public static int getInt(byte[] data, int offset) { + + int l = 0; + for (int k = 0; k < 4; k++) { + l = (l << 8) | (data[offset++] & 0xFF); + } + return l; + } + + /** + * Calculates SHA-1 hash for given data. + * @param inBuf array containing the data + * @param inOff data offset + * @param inLen data length + * @return SHA-1 hash + */ + public static byte[] getHash(byte[] inBuf, int inOff, int inLen) { + + try { + MessageDigest sha = MessageDigest.getInstance("SHA"); + sha.reset(); + byte[] hash = new byte[20]; + hash = sha.digest(inBuf); + return hash; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * Returns byte array which contains encoded short value. + * @param i the value + * @return byte array + */ + public static byte[] shortToBytes(int i) { + + byte[] data = new byte[2]; + data[0] = (byte) (i >> 8); + data[1] = (byte) i; + return data; + } + + /** + * Returns byte array that contains sequence of encoded short values. + * @param data the short values + * @return byte array + */ + + public static byte[] shortsToBytes(short[] data) { + + byte[] d = new byte[2 * data.length]; + for (int i = 0; i < data.length; i++) { + d[i * 2] = (byte) (data[i] >> 8); + d[i * 2 + 1] = (byte) data[i]; + } + return d; + } + + /** + * Returns UTF 8 encoding for this string. + * @param s the string + * @return UTF 8 encoding + */ + public static byte[] stringToBytes(String s) { + try { + return s.getBytes(utf8); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + System.out.println("Internal error: unsupported encoding"); + return null; + } + + /** + * Converts the calender to a string. + * @param calendar input date information + * @return formatted calendar string + */ + public static String calendarToString(Calendar calendar) { + String[] months = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + String[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", + "Sat" }; + + if (calendar == null) { + return "Thu Jan 01 00:00:00 UTC 1970"; + } + + int dow = calendar.get(Calendar.DAY_OF_WEEK); + int month = calendar.get(Calendar.MONTH); + int day = calendar.get(Calendar.DAY_OF_MONTH); + int hour_of_day = calendar.get(Calendar.HOUR_OF_DAY); + int minute = calendar.get(Calendar.MINUTE); + int seconds = calendar.get(Calendar.SECOND); + int year = calendar.get(Calendar.YEAR); + + String yr = Integer.toString(year); + + // TimeZone zone = calendar.getTimeZone(); + // String zoneID = zone.getID(); + // if (zoneID == null) zoneID = ""; + String zoneID = "GMT"; + + // The total size of the string buffer + // 3+1+3+1+2+1+2+1+2+1+2+1+zoneID.length+1+yr.length + // = 21 + zoneID.length + yr.length + StringBuffer sb = new StringBuffer(25 + zoneID.length() + + yr.length()); + + sb.append(days[dow - 1]).append(' '); + sb.append(months[month]).append(' '); + appendTwoDigits(sb, day).append(' '); + appendTwoDigits(sb, hour_of_day).append(':'); + appendTwoDigits(sb, minute).append(':'); + appendTwoDigits(sb, seconds).append(' '); + if (zoneID.length() > 0) + sb.append(zoneID).append(' '); + appendFourDigits(sb, year); + + return sb.toString(); + } + + /** + * Appends zero filled numeric string for two digit numbers. + * @param sb current formatted buffer + * @param number the digit to format + * @return updated formatted string buffer + */ + private static final StringBuffer appendTwoDigits(StringBuffer sb, + int number) { + if (number < 10) { + sb.append('0'); + } + return sb.append(number); + } + + /** + * Appends zero filled numeric string for four digit numbers. + * @param sb current formatted buffer + * @param number the digit to format + * @return updated formatted string buffer + */ + private static final StringBuffer appendFourDigits(StringBuffer sb, + int number) { + if (number >= 0 && number < 1000) { + sb.append('0'); + if (number < 100) { + sb.append('0'); + } + if (number < 10) { + sb.append('0'); + } + } + return sb.append(number); + } + + /** + * Writes hex representation of byte array elements. + * @param writer where to write + * @param data data to be written + */ + public static void writeHex(PrintStream writer, byte[] data) { + + String s = ""; + + for (int i = 0; i < data.length; i++) { + + if (data[i] > -1 && data[i] < 16) { + s = s + "0"; + } + s = s + Integer.toHexString(data[i] & 0xff) + " "; + + if ((i + 1) % 16 == 0) { + writer.println(s); + s = ""; + } + } + + if (s.length() != 4) { + writer.println(s); + } + } + + /** + * Converts string to array of shorts + * @param str input string + * @return output array of shorts + */ + public static short[] stringToShorts(String str) { + byte[] b = str.getBytes(); + short[] res = new short[1 + (b.length / 4)]; + for (int i = 0; i < b.length; i++) { + if ((b[i] >= 0x30) & (b[i] <= 0x39)) { + b[i] = (byte) (b[i] - 0x30); + } else { + if ((b[i] >= 0x41) & (b[i] <= 0x46)) { + b[i] = (byte) (b[i] - 0x41 + 0xa); + } else { + if ((b[i] >= 0x61) & (b[i] <= 0x66)) { + b[i] = (byte) (b[i] - 0x61 + 0xa); + } + } + + } + } + res[0] = 0x3fff; + for (int i = 0; i < res.length - 1; i++) { + res[i + 1] = (short) ((b[4 * i] << 12) + | (b[4 * i + 1] << 8) | (b[4 * i + 2] << 4) | b[4 * i + 3]); + } + return res; + } + + /** + * Creates java source for static array initialization. + * @param writer where to write + * @param name array name + * @param data initial values + */ + public static void writeDataArray(PrintStream writer, String name, + byte[] data) { + + writer.println(); + + String s = " static byte[] " + name + " = { "; + + for (int i = 0; i < data.length; i++) { + + if (i != 0) { + s = s + ", "; + } + + String h = "" + data[i]; + + if (s.length() + h.length() > 76) { + writer.println(s); + s = " "; + } + + s = s + h; + } + + writer.println(s + "};"); + writer.println(); + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/DeserializationProcedureState.java b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/DeserializationProcedureState.java index 85e1ebd4..6044b852 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/DeserializationProcedureState.java +++ b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/DeserializationProcedureState.java @@ -1,10 +1,10 @@ -package ecologylab.serialization.deserializers.pullhandlers; - -public enum DeserializationProcedureState -{ - INIT, - ATTRIBUTES, - ATTRIBUTES_DONE, - ELEMENTS, - ELEMENTS_DONE, -} +package ecologylab.serialization.deserializers.pullhandlers; + +public enum DeserializationProcedureState +{ + INIT, + ATTRIBUTES, + ATTRIBUTES_DONE, + ELEMENTS, + ELEMENTS_DONE, +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/PullDeserializer.java b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/PullDeserializer.java index f92e1220..1105383a 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/PullDeserializer.java +++ b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/PullDeserializer.java @@ -1,350 +1,350 @@ -package ecologylab.serialization.deserializers.pullhandlers; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.charset.Charset; - -import ecologylab.generic.Debug; -import ecologylab.net.ConnectionAdapter; -import ecologylab.net.PURLConnection; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.DeserializationHookStrategy; -import ecologylab.serialization.FieldType; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.deserializers.ISimplDeserializationIn; -import ecologylab.serialization.deserializers.ISimplDeserializationPost; -import ecologylab.serialization.deserializers.ISimplDeserializationPre; -import ecologylab.serialization.deserializers.pullhandlers.binaryformats.BinaryPullDeserializer; -import ecologylab.serialization.deserializers.pullhandlers.binaryformats.TLVPullDeserializer; -import ecologylab.serialization.deserializers.pullhandlers.stringformats.JSONPullDeserializer; -import ecologylab.serialization.deserializers.pullhandlers.stringformats.StringPullDeserializer; -import ecologylab.serialization.deserializers.pullhandlers.stringformats.XMLPullDeserializer; -import ecologylab.serialization.formatenums.BinaryFormat; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -public abstract class PullDeserializer extends Debug -{ - - protected SimplTypesScope translationScope; - - protected TranslationContext translationContext; - - protected DeserializationHookStrategy deserializationHookStrategy; - - static final ConnectionAdapter connectionAdapter = new ConnectionAdapter(); - - /** - * Constructs that creates a JSON deserialization handler - * - * @param translationScope - * translation scope to use for de/serializing subsequent char sequences - * @param translationContext - * used for graph handling - */ - public PullDeserializer(SimplTypesScope translationScope, TranslationContext translationContext) - { - this.translationScope = translationScope; - this.translationContext = translationContext; - this.deserializationHookStrategy = null; - } - - /** - * Constructs that creates a JSON deserialization handler - * - * @param translationScope - * translation scope to use for de/serializing subsequent char sequences - * @param translationContext - * used for graph handling - */ - public PullDeserializer(SimplTypesScope translationScope, TranslationContext translationContext, - DeserializationHookStrategy deserializationHookStrategy) - { - this.translationScope = translationScope; - this.translationContext = translationContext; - this.deserializationHookStrategy = deserializationHookStrategy; - } - - /** - * - * @param file - * @return - * @throws SIMPLTranslationException - */ - public Object parse(File file) throws SIMPLTranslationException - { - try - { - FileInputStream fileInputStream = new FileInputStream(file); - BufferedInputStream bufferedStream = new BufferedInputStream(fileInputStream); - - this.translationContext.setBaseDirFile(file.getParentFile()); - - Object object = parse(bufferedStream); - bufferedStream.close(); - return object; - } - catch (FileNotFoundException e) - { - throw new SIMPLTranslationException("Can't open file " + file.getAbsolutePath(), e); - } - catch (IOException e) - { - throw new SIMPLTranslationException("Can't close file " + file.getAbsolutePath(), e); - } - - } - - /** - * - * @param purl - * @return - * @throws SIMPLTranslationException - */ - public Object parse(ParsedURL purl) throws SIMPLTranslationException - { - if (purl.isFile()) - return parse(purl.file()); - - PURLConnection purlConnection = purl.connect(connectionAdapter); - Object result = parse(purlConnection.inputStream()); - purlConnection.recycle(); - return result; - } - - /** - * - * @param url - * @return - * @throws SIMPLTranslationException - */ - public Object parse(URL url) throws SIMPLTranslationException - { - return parse(new ParsedURL(url)); - } - - /** - * - * @param inputStream - * @param charSet - * @return - * @throws SIMPLTranslationException - */ - public abstract Object parse(InputStream inputStream, Charset charSet) - throws SIMPLTranslationException; - - /** - * - * @param inputStream - * @return - * @throws SIMPLTranslationException - */ - public abstract Object parse(InputStream inputStream) throws SIMPLTranslationException; - - /** - * - * @param object - * @param translationContext - * TODO - */ - protected void deserializationPreHook(Object object, TranslationContext translationContext) - { - if (object instanceof ISimplDeserializationPre) - { - ((ISimplDeserializationPre) object).deserializationPreHook(translationContext); - } - } - - /** - * - * @param subRoot - * @param translationContext - */ - protected void deserializationInHook(Object object, TranslationContext translationContext) - { - if (object instanceof ISimplDeserializationIn) - { - ((ISimplDeserializationIn) object).deserializationInHook(translationContext); - } - } - - /** - * - * @param object - * @param translationContext - * TODO - */ - protected void deserializationPostHook(Object object, TranslationContext translationContext) - { - if (object instanceof ISimplDeserializationPost) - { - ((ISimplDeserializationPost) object).deserializationPostHook(translationContext, object); - } - } - - /** - * - * @param translationScope - * @param translationContext - * @param format - * @return - * @throws SIMPLTranslationException - */ - public static PullDeserializer getDeserializer(SimplTypesScope translationScope, - TranslationContext translationContext, Format format) throws SIMPLTranslationException - { - return getDeserializer(translationScope, translationContext, null, format); - } - - /** - * - * @param translationScope - * @param translationContext - * @param deserializationHookStrategy - * @param format - * @return - * @throws SIMPLTranslationException - */ - - public static PullDeserializer getDeserializer(SimplTypesScope translationScope, - TranslationContext translationContext, - DeserializationHookStrategy deserializationHookStrategy, Format format) - throws SIMPLTranslationException - { - switch (format) - { - case XML: - return new XMLPullDeserializer(translationScope, - translationContext, deserializationHookStrategy); - case JSON: - return new JSONPullDeserializer(translationScope, translationContext, - deserializationHookStrategy); - case TLV: - return new TLVPullDeserializer(translationScope, translationContext, - deserializationHookStrategy); - case BIBTEX: - // TODO bibtex pull deserializer not implemented! -// return new BibTeXPullDeserializer(translationScope, translationContext); - default: - throw new SIMPLTranslationException(format + " format not supported"); - } - } - - /** - * - * @param translationScope - * @param translationContext - * @param stringFormat - * @return - * @throws SIMPLTranslationException - */ - public static StringPullDeserializer getStringDeserializer(SimplTypesScope translationScope, - TranslationContext translationContext, StringFormat stringFormat) - throws SIMPLTranslationException - { - return getStringDeserializer(translationScope, translationContext, null, stringFormat); - } - - /** - * - * @param translationScope - * @param translationContext - * @param deserializationHookStrategy - * @param stringFormat - * @return - * @throws SIMPLTranslationException - */ - public static StringPullDeserializer getStringDeserializer(SimplTypesScope translationScope, - TranslationContext translationContext, - DeserializationHookStrategy deserializationHookStrategy, StringFormat stringFormat) - throws SIMPLTranslationException - { - switch (stringFormat) - { - case XML: - return new XMLPullDeserializer(translationScope, - translationContext, deserializationHookStrategy); - case JSON: - return new JSONPullDeserializer(translationScope, translationContext, - deserializationHookStrategy); - case BIBTEX: - // TODO bibtex pull deserializer not implemented! -// return new BibTeXPullDeserializer(translationScope, translationContext); - default: - throw new SIMPLTranslationException(stringFormat + " format not supported"); - } - } - - /** - * - * @param translationScope - * @param translationContext - * @param binaryFormat - * @return - * @throws SIMPLTranslationException - */ - public static BinaryPullDeserializer getBinaryDeserializer(SimplTypesScope translationScope, - TranslationContext translationContext, BinaryFormat binaryFormat) - throws SIMPLTranslationException - { - return getBinaryDeserializer(translationScope, translationContext, null, binaryFormat); - } - - /** - * - * @param translationScope - * @param translationContext - * @param deserializationHookStrategy - * @param binaryFormat - * @return - * @throws SIMPLTranslationException - */ - public static BinaryPullDeserializer getBinaryDeserializer(SimplTypesScope translationScope, - TranslationContext translationContext, - DeserializationHookStrategy deserializationHookStrategy, BinaryFormat binaryFormat) - throws SIMPLTranslationException - { - switch (binaryFormat) - { - case TLV: - default: - throw new SIMPLTranslationException(binaryFormat + " format not supported"); - } - } - - /** - * a state machine of deserialization states, e.g. now dealing with attributes or elements - * - * @param state - * @param fieldType - * @return - */ - protected DeserializationProcedureState nextDeserializationProcedureState( - DeserializationProcedureState state, FieldType fieldType) - { - // This is for backwards compat. Waiting to change this interface. - // TODO: Fix this. - FieldType ft = fieldType; - switch (ft) - { - case SCALAR: - if (state == DeserializationProcedureState.INIT) - state = DeserializationProcedureState.ATTRIBUTES; - // otherwise remain the same - break; - default: - if (state == DeserializationProcedureState.INIT || state == DeserializationProcedureState.ATTRIBUTES) - state = DeserializationProcedureState.ATTRIBUTES_DONE; - // otherwise remain the same - } - return state; - } - -} +package ecologylab.serialization.deserializers.pullhandlers; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.charset.Charset; + +import ecologylab.generic.Debug; +import ecologylab.net.ConnectionAdapter; +import ecologylab.net.PURLConnection; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.DeserializationHookStrategy; +import ecologylab.serialization.FieldType; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.deserializers.ISimplDeserializationIn; +import ecologylab.serialization.deserializers.ISimplDeserializationPost; +import ecologylab.serialization.deserializers.ISimplDeserializationPre; +import ecologylab.serialization.deserializers.pullhandlers.binaryformats.BinaryPullDeserializer; +import ecologylab.serialization.deserializers.pullhandlers.binaryformats.TLVPullDeserializer; +import ecologylab.serialization.deserializers.pullhandlers.stringformats.JSONPullDeserializer; +import ecologylab.serialization.deserializers.pullhandlers.stringformats.StringPullDeserializer; +import ecologylab.serialization.deserializers.pullhandlers.stringformats.XMLPullDeserializer; +import ecologylab.serialization.formatenums.BinaryFormat; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +public abstract class PullDeserializer extends Debug +{ + + protected SimplTypesScope translationScope; + + protected TranslationContext translationContext; + + protected DeserializationHookStrategy deserializationHookStrategy; + + static final ConnectionAdapter connectionAdapter = new ConnectionAdapter(); + + /** + * Constructs that creates a JSON deserialization handler + * + * @param translationScope + * translation scope to use for de/serializing subsequent char sequences + * @param translationContext + * used for graph handling + */ + public PullDeserializer(SimplTypesScope translationScope, TranslationContext translationContext) + { + this.translationScope = translationScope; + this.translationContext = translationContext; + this.deserializationHookStrategy = null; + } + + /** + * Constructs that creates a JSON deserialization handler + * + * @param translationScope + * translation scope to use for de/serializing subsequent char sequences + * @param translationContext + * used for graph handling + */ + public PullDeserializer(SimplTypesScope translationScope, TranslationContext translationContext, + DeserializationHookStrategy deserializationHookStrategy) + { + this.translationScope = translationScope; + this.translationContext = translationContext; + this.deserializationHookStrategy = deserializationHookStrategy; + } + + /** + * + * @param file + * @return + * @throws SIMPLTranslationException + */ + public Object parse(File file) throws SIMPLTranslationException + { + try + { + FileInputStream fileInputStream = new FileInputStream(file); + BufferedInputStream bufferedStream = new BufferedInputStream(fileInputStream); + + this.translationContext.setBaseDirFile(file.getParentFile()); + + Object object = parse(bufferedStream); + bufferedStream.close(); + return object; + } + catch (FileNotFoundException e) + { + throw new SIMPLTranslationException("Can't open file " + file.getAbsolutePath(), e); + } + catch (IOException e) + { + throw new SIMPLTranslationException("Can't close file " + file.getAbsolutePath(), e); + } + + } + + /** + * + * @param purl + * @return + * @throws SIMPLTranslationException + */ + public Object parse(ParsedURL purl) throws SIMPLTranslationException + { + if (purl.isFile()) + return parse(purl.file()); + + PURLConnection purlConnection = purl.connect(connectionAdapter); + Object result = parse(purlConnection.inputStream()); + purlConnection.recycle(); + return result; + } + + /** + * + * @param url + * @return + * @throws SIMPLTranslationException + */ + public Object parse(URL url) throws SIMPLTranslationException + { + return parse(new ParsedURL(url)); + } + + /** + * + * @param inputStream + * @param charSet + * @return + * @throws SIMPLTranslationException + */ + public abstract Object parse(InputStream inputStream, Charset charSet) + throws SIMPLTranslationException; + + /** + * + * @param inputStream + * @return + * @throws SIMPLTranslationException + */ + public abstract Object parse(InputStream inputStream) throws SIMPLTranslationException; + + /** + * + * @param object + * @param translationContext + * TODO + */ + protected void deserializationPreHook(Object object, TranslationContext translationContext) + { + if (object instanceof ISimplDeserializationPre) + { + ((ISimplDeserializationPre) object).deserializationPreHook(translationContext); + } + } + + /** + * + * @param subRoot + * @param translationContext + */ + protected void deserializationInHook(Object object, TranslationContext translationContext) + { + if (object instanceof ISimplDeserializationIn) + { + ((ISimplDeserializationIn) object).deserializationInHook(translationContext); + } + } + + /** + * + * @param object + * @param translationContext + * TODO + */ + protected void deserializationPostHook(Object object, TranslationContext translationContext) + { + if (object instanceof ISimplDeserializationPost) + { + ((ISimplDeserializationPost) object).deserializationPostHook(translationContext, object); + } + } + + /** + * + * @param translationScope + * @param translationContext + * @param format + * @return + * @throws SIMPLTranslationException + */ + public static PullDeserializer getDeserializer(SimplTypesScope translationScope, + TranslationContext translationContext, Format format) throws SIMPLTranslationException + { + return getDeserializer(translationScope, translationContext, null, format); + } + + /** + * + * @param translationScope + * @param translationContext + * @param deserializationHookStrategy + * @param format + * @return + * @throws SIMPLTranslationException + */ + + public static PullDeserializer getDeserializer(SimplTypesScope translationScope, + TranslationContext translationContext, + DeserializationHookStrategy deserializationHookStrategy, Format format) + throws SIMPLTranslationException + { + switch (format) + { + case XML: + return new XMLPullDeserializer(translationScope, + translationContext, deserializationHookStrategy); + case JSON: + return new JSONPullDeserializer(translationScope, translationContext, + deserializationHookStrategy); + case TLV: + return new TLVPullDeserializer(translationScope, translationContext, + deserializationHookStrategy); + case BIBTEX: + // TODO bibtex pull deserializer not implemented! +// return new BibTeXPullDeserializer(translationScope, translationContext); + default: + throw new SIMPLTranslationException(format + " format not supported"); + } + } + + /** + * + * @param translationScope + * @param translationContext + * @param stringFormat + * @return + * @throws SIMPLTranslationException + */ + public static StringPullDeserializer getStringDeserializer(SimplTypesScope translationScope, + TranslationContext translationContext, StringFormat stringFormat) + throws SIMPLTranslationException + { + return getStringDeserializer(translationScope, translationContext, null, stringFormat); + } + + /** + * + * @param translationScope + * @param translationContext + * @param deserializationHookStrategy + * @param stringFormat + * @return + * @throws SIMPLTranslationException + */ + public static StringPullDeserializer getStringDeserializer(SimplTypesScope translationScope, + TranslationContext translationContext, + DeserializationHookStrategy deserializationHookStrategy, StringFormat stringFormat) + throws SIMPLTranslationException + { + switch (stringFormat) + { + case XML: + return new XMLPullDeserializer(translationScope, + translationContext, deserializationHookStrategy); + case JSON: + return new JSONPullDeserializer(translationScope, translationContext, + deserializationHookStrategy); + case BIBTEX: + // TODO bibtex pull deserializer not implemented! +// return new BibTeXPullDeserializer(translationScope, translationContext); + default: + throw new SIMPLTranslationException(stringFormat + " format not supported"); + } + } + + /** + * + * @param translationScope + * @param translationContext + * @param binaryFormat + * @return + * @throws SIMPLTranslationException + */ + public static BinaryPullDeserializer getBinaryDeserializer(SimplTypesScope translationScope, + TranslationContext translationContext, BinaryFormat binaryFormat) + throws SIMPLTranslationException + { + return getBinaryDeserializer(translationScope, translationContext, null, binaryFormat); + } + + /** + * + * @param translationScope + * @param translationContext + * @param deserializationHookStrategy + * @param binaryFormat + * @return + * @throws SIMPLTranslationException + */ + public static BinaryPullDeserializer getBinaryDeserializer(SimplTypesScope translationScope, + TranslationContext translationContext, + DeserializationHookStrategy deserializationHookStrategy, BinaryFormat binaryFormat) + throws SIMPLTranslationException + { + switch (binaryFormat) + { + case TLV: + default: + throw new SIMPLTranslationException(binaryFormat + " format not supported"); + } + } + + /** + * a state machine of deserialization states, e.g. now dealing with attributes or elements + * + * @param state + * @param fieldType + * @return + */ + protected DeserializationProcedureState nextDeserializationProcedureState( + DeserializationProcedureState state, FieldType fieldType) + { + // This is for backwards compat. Waiting to change this interface. + // TODO: Fix this. + FieldType ft = fieldType; + switch (ft) + { + case SCALAR: + if (state == DeserializationProcedureState.INIT) + state = DeserializationProcedureState.ATTRIBUTES; + // otherwise remain the same + break; + default: + if (state == DeserializationProcedureState.INIT || state == DeserializationProcedureState.ATTRIBUTES) + state = DeserializationProcedureState.ATTRIBUTES_DONE; + // otherwise remain the same + } + return state; + } + +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/binaryformats/BinaryPullDeserializer.java b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/binaryformats/BinaryPullDeserializer.java index 0f2d240a..7e443a65 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/binaryformats/BinaryPullDeserializer.java +++ b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/binaryformats/BinaryPullDeserializer.java @@ -1,18 +1,18 @@ -package ecologylab.serialization.deserializers.pullhandlers.binaryformats; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.deserializers.pullhandlers.PullDeserializer; - -public abstract class BinaryPullDeserializer extends PullDeserializer -{ - - public BinaryPullDeserializer(SimplTypesScope translationScope, - TranslationContext translationContext) - { - super(translationScope, translationContext); - } - - public abstract Object parse(byte[] byteArray) throws SIMPLTranslationException; -} +package ecologylab.serialization.deserializers.pullhandlers.binaryformats; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.deserializers.pullhandlers.PullDeserializer; + +public abstract class BinaryPullDeserializer extends PullDeserializer +{ + + public BinaryPullDeserializer(SimplTypesScope translationScope, + TranslationContext translationContext) + { + super(translationScope, translationContext); + } + + public abstract Object parse(byte[] byteArray) throws SIMPLTranslationException; +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/BibTeXPullDeserializer.java b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/BibTeXPullDeserializer.java index fbdf83fa..a796f414 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/BibTeXPullDeserializer.java +++ b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/BibTeXPullDeserializer.java @@ -1,208 +1,208 @@ -package ecologylab.serialization.deserializers.pullhandlers.stringformats; - -import java.io.File; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.util.Collection; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.FieldType; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.deserializers.parsers.bibtex.BibTeXEvents; - -public class BibTeXPullDeserializer extends StringPullDeserializer implements BibTeXEvents, - ScalarUnmarshallingContext -{ - - ParsedURL purlContext; - - File fileContext; - - Object root = null; - - String currentTag; - - FieldDescriptor currentFD; - - public BibTeXPullDeserializer(SimplTypesScope tscope) - { - this(tscope, null); - } - - public BibTeXPullDeserializer(SimplTypesScope tscope, TranslationContext tcontext) - { - super(tscope, tcontext); - } - - @Override - public void startBibTeX() - { - // System.out.println("started:"); - root = null; - } - - @Override - public void startEntity(String typeName) - { - // System.out.println("entity: " + typeName); - if (root == null && typeName != null) - { - ClassDescriptor rootClassD = translationScope.getClassDescriptorByBibTeXType(typeName.toLowerCase()); - if (rootClassD != null) - { - try - { - root = rootClassD.getInstance(); - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - else - { - warning("no ClassDescriptor found for bibTeX type " + typeName); - } - } - } - - @Override - public void key(String key) - { - // System.out.println("key: " + key); - if (root != null) - { - FieldDescriptor keyFD = ClassDescriptor.getClassDescriptor(root) - .getFieldDescriptorForBibTeXKey(); - if (keyFD != null) - { - keyFD.setFieldToScalar(root, key, this); - } - } - } - - @Override - public void startTag(String tagName) - { - // System.out.println("tag: " + tagName); - if (root != null && tagName != null) - { - currentTag = tagName.toLowerCase(); - currentFD = ClassDescriptor.getClassDescriptor(root).getFieldDescriptorByBibTeXTag(tagName); - if (currentFD == null) - { - warning("ignoring bibTeX tag: " + tagName); - } - } - } - - @Override - public void endTag() - { - // System.out.println("endtag;"); - currentFD = null; - currentTag = null; - } - - @Override - public void value(String value) - { - // System.out.println("value: " + value); - if (currentFD != null && root != null) - { - FieldType type = currentFD.getType(); - - switch (type) - { - case SCALAR: - currentFD.setFieldToScalar(root, value, this); - break; - case COLLECTION_SCALAR: - Collection collection = (Collection) currentFD.automaticLazyGetCollectionOrMap(root); - if ("author".equals(currentTag)) - { - String[] authorNames = value.split("and"); - for (String authorName : authorNames) - { - collection.add(authorName.trim()); - } - } - else - { - String[] items = value.split(translationContext.getDelimiter()); - for (String item : items) - { - collection.add(item); - } - } - break; - } - } - } - - @Override - public void endEntity() - { - // System.out.println("endentity;"); - root = null; - } - - @Override - public void endBibTeX() - { - // System.out.println("end."); - } - - @Override - public Object getBibTeXObject() - { - return root; - } - - @Override - public ParsedURL purlContext() - { - return purlContext; - } - - @Override - public File fileContext() - { - if (fileContext != null) - return fileContext; - ParsedURL purlContext = purlContext(); - if (purlContext != null) - { - return purlContext.file(); - } - return null; - } - - @Override - public Object parse(CharSequence charSequence) throws SIMPLTranslationException - { - // TODO Auto-generated method stub - return null; - } - - @Override - public Object parse(InputStream inputStream) throws SIMPLTranslationException - { - // TODO Auto-generated method stub - return null; - } - - @Override - public Object parse(InputStream inputStream, Charset charSet) throws SIMPLTranslationException - { - // TODO Auto-generated method stub - return null; - } - -} +package ecologylab.serialization.deserializers.pullhandlers.stringformats; + +import java.io.File; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Collection; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.FieldType; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.deserializers.parsers.bibtex.BibTeXEvents; + +public class BibTeXPullDeserializer extends StringPullDeserializer implements BibTeXEvents, + ScalarUnmarshallingContext +{ + + ParsedURL purlContext; + + File fileContext; + + Object root = null; + + String currentTag; + + FieldDescriptor currentFD; + + public BibTeXPullDeserializer(SimplTypesScope tscope) + { + this(tscope, null); + } + + public BibTeXPullDeserializer(SimplTypesScope tscope, TranslationContext tcontext) + { + super(tscope, tcontext); + } + + @Override + public void startBibTeX() + { + // System.out.println("started:"); + root = null; + } + + @Override + public void startEntity(String typeName) + { + // System.out.println("entity: " + typeName); + if (root == null && typeName != null) + { + ClassDescriptor rootClassD = translationScope.getClassDescriptorByBibTeXType(typeName.toLowerCase()); + if (rootClassD != null) + { + try + { + root = rootClassD.getInstance(); + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + else + { + warning("no ClassDescriptor found for bibTeX type " + typeName); + } + } + } + + @Override + public void key(String key) + { + // System.out.println("key: " + key); + if (root != null) + { + FieldDescriptor keyFD = ClassDescriptor.getClassDescriptor(root) + .getFieldDescriptorForBibTeXKey(); + if (keyFD != null) + { + keyFD.setFieldToScalar(root, key, this); + } + } + } + + @Override + public void startTag(String tagName) + { + // System.out.println("tag: " + tagName); + if (root != null && tagName != null) + { + currentTag = tagName.toLowerCase(); + currentFD = ClassDescriptor.getClassDescriptor(root).getFieldDescriptorByBibTeXTag(tagName); + if (currentFD == null) + { + warning("ignoring bibTeX tag: " + tagName); + } + } + } + + @Override + public void endTag() + { + // System.out.println("endtag;"); + currentFD = null; + currentTag = null; + } + + @Override + public void value(String value) + { + // System.out.println("value: " + value); + if (currentFD != null && root != null) + { + FieldType type = currentFD.getType(); + + switch (type) + { + case SCALAR: + currentFD.setFieldToScalar(root, value, this); + break; + case COLLECTION_SCALAR: + Collection collection = (Collection) currentFD.automaticLazyGetCollectionOrMap(root); + if ("author".equals(currentTag)) + { + String[] authorNames = value.split("and"); + for (String authorName : authorNames) + { + collection.add(authorName.trim()); + } + } + else + { + String[] items = value.split(translationContext.getDelimiter()); + for (String item : items) + { + collection.add(item); + } + } + break; + } + } + } + + @Override + public void endEntity() + { + // System.out.println("endentity;"); + root = null; + } + + @Override + public void endBibTeX() + { + // System.out.println("end."); + } + + @Override + public Object getBibTeXObject() + { + return root; + } + + @Override + public ParsedURL purlContext() + { + return purlContext; + } + + @Override + public File fileContext() + { + if (fileContext != null) + return fileContext; + ParsedURL purlContext = purlContext(); + if (purlContext != null) + { + return purlContext.file(); + } + return null; + } + + @Override + public Object parse(CharSequence charSequence) throws SIMPLTranslationException + { + // TODO Auto-generated method stub + return null; + } + + @Override + public Object parse(InputStream inputStream) throws SIMPLTranslationException + { + // TODO Auto-generated method stub + return null; + } + + @Override + public Object parse(InputStream inputStream, Charset charSet) throws SIMPLTranslationException + { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/JSONPullDeserializer.java b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/JSONPullDeserializer.java index 7c514c50..0f357814 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/JSONPullDeserializer.java +++ b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/JSONPullDeserializer.java @@ -12,7 +12,6 @@ import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.JsonToken; - import ecologylab.serialization.ClassDescriptor; import ecologylab.serialization.DeserializationHookStrategy; import ecologylab.serialization.FieldDescriptor; @@ -20,6 +19,7 @@ import ecologylab.serialization.SIMPLTranslationException; import ecologylab.serialization.SimplTypesScope; import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.XMLTools; import ecologylab.serialization.deserializers.pullhandlers.DeserializationProcedureState; import ecologylab.serialization.types.element.IMappable; @@ -155,7 +155,7 @@ private Object parse() throws IOException, JsonParseException, SIMPLTranslationE // Logic to set all field descritpro scalars to defaults. for(FieldDescriptor fd : rootClassDescriptor.allFieldDescriptors()) { - if(fd.isScalar() && (fd.isEnum() == false)) + if(fd.isScalar() && !fd.isCollection() && !fd.isEnum()) { fd.setFieldToScalarDefault(root, translationContext); } @@ -192,13 +192,13 @@ private Object parse() throws IOException, JsonParseException, SIMPLTranslationE private void createObjectModel(Object root, ClassDescriptor rootClassDescriptor) throws JsonParseException, IOException, SIMPLTranslationException { - debug(debugContext.toString() - + "createObjectModel(" - + (root == null ? "" : root.toString()) - + ", " - + (rootClassDescriptor == null ? "" : rootClassDescriptor.toString()) - + ")"); - debugContext.append("----"); +// debug(debugContext.toString() +// + "createObjectModel(" +// + (root == null ? "" : root.toString()) +// + ", " +// + (rootClassDescriptor == null ? "" : rootClassDescriptor.toString()) +// + ")"); +// debugContext.append("----"); FieldDescriptor currentFieldDescriptor = null; Object subRoot = null; @@ -235,14 +235,37 @@ private void createObjectModel(Object root, ClassDescriptor rootClassDescriptor) { path = 3; fieldTag = jp.getText(); - currentFieldDescriptor = rootClassDescriptor.getFieldDescriptorByTag(fieldTag, translationScope, null); +// currentFieldDescriptor = rootClassDescriptor.getFieldDescriptorByTag(fieldTag, translationScope, null); + String fieldName = XMLTools.fieldNameFromElementName(fieldTag); + currentFieldDescriptor = rootClassDescriptor.getFieldDescriptorByFieldName(fieldName); + if (currentFieldDescriptor == null) + { + currentFieldDescriptor = + rootClassDescriptor.getFieldDescriptorByTag(fieldTag, translationScope); + } } } + if (currentFieldDescriptor == null) + { + error("Cannot find a FieldDescriptor for tag " + fieldTag); + continue; + } + FieldType fieldType = currentFieldDescriptor.getType(); - String message = debugContext.toString() + "processing field " + currentFieldDescriptor.getName(); - debug(message); + boolean deWrap = false; + if (fieldType == FieldType.COMPOSITE_ELEMENT + && currentFieldDescriptor.isPolymorphic() + && currentFieldDescriptor.getWrapper() != null) + { + deWrap = true; + jp.nextToken(); + jp.nextToken(); + } + +// String message = debugContext.toString() + "processing field " + currentFieldDescriptor.getName(); +// debug(message); switch (fieldType) { @@ -253,16 +276,19 @@ private void createObjectModel(Object root, ClassDescriptor rootClassDescriptor) case COMPOSITE_ELEMENT: jp.nextToken(); - String tagName = jp.getCurrentName(); - subRoot = getSubRoot(currentFieldDescriptor, tagName); - - ClassDescriptor subRootClassDescriptor = currentFieldDescriptor - .getChildClassDescriptor(tagName); - - // if (subRoot != null) - // subRoot.setupInParent(root, subRootClassDescriptor); - - currentFieldDescriptor.setFieldToComposite(root, subRoot); + if (currentFieldDescriptor.isPolymorphic()) + { + jp.nextToken(); // FIELD_NAME (which indicates the type) + jp.nextToken(); // START_OBJECT + + subRoot = deserializeComposite(root, currentFieldDescriptor); + + jp.nextToken(); // END_OBJECT + } + else + { + subRoot = deserializeComposite(root, currentFieldDescriptor); + } break; case COLLECTION_ELEMENT: jp.nextToken(); @@ -270,7 +296,7 @@ private void createObjectModel(Object root, ClassDescriptor rootClassDescriptor) if (currentFieldDescriptor.isPolymorphic()) { // ignore the wrapper tag - if (!currentFieldDescriptor.isWrapped()) + if (currentFieldDescriptor.isWrapped()) jp.nextToken(); while (jp.getCurrentToken() != JsonToken.END_ARRAY) @@ -278,10 +304,7 @@ private void createObjectModel(Object root, ClassDescriptor rootClassDescriptor) jp.nextToken(); jp.nextToken(); - subRoot = getSubRoot(currentFieldDescriptor, jp.getCurrentName()); - Collection collection = (Collection) currentFieldDescriptor - .automaticLazyGetCollectionOrMap(root); - collection.add(subRoot); + subRoot = deserializeCollectionElement(root, currentFieldDescriptor); jp.nextToken(); jp.nextToken(); @@ -291,10 +314,7 @@ private void createObjectModel(Object root, ClassDescriptor rootClassDescriptor) { while (jp.nextToken() != JsonToken.END_ARRAY) { - subRoot = getSubRoot(currentFieldDescriptor, jp.getCurrentName()); - Collection collection = (Collection) currentFieldDescriptor - .automaticLazyGetCollectionOrMap(root); - collection.add(subRoot); + subRoot = deserializeCollectionElement(root, currentFieldDescriptor); } } break; @@ -348,12 +368,16 @@ private void createObjectModel(Object root, ClassDescriptor rootClassDescriptor) } break; case WRAPPER: - if (!currentFieldDescriptor.getWrappedFD().isPolymorphic()) jp.nextToken(); break; } + if (deWrap) + { + jp.nextToken(); + } + state = nextDeserializationProcedureState(state, fieldType); if (state == DeserializationProcedureState.ATTRIBUTES_DONE) { @@ -381,6 +405,34 @@ private void createObjectModel(Object root, ClassDescriptor rootClassDescriptor) debugContext.delete(debugContextLen - 4, debugContextLen); } + private Object deserializeCollectionElement(Object root, + FieldDescriptor currentFieldDescriptor) + throws SIMPLTranslationException, JsonParseException, IOException { + Object subRoot; + subRoot = getSubRoot(currentFieldDescriptor, jp.getCurrentName()); + Collection collection = (Collection) currentFieldDescriptor + .automaticLazyGetCollectionOrMap(root); + collection.add(subRoot); + return subRoot; + } + + private Object deserializeComposite(Object root, + FieldDescriptor currentFieldDescriptor) throws IOException, + JsonParseException, SIMPLTranslationException { + Object subRoot; + String tagName = jp.getCurrentName(); + subRoot = getSubRoot(currentFieldDescriptor, tagName); + + ClassDescriptor subRootClassDescriptor = currentFieldDescriptor + .getChildClassDescriptor(tagName); + + // if (subRoot != null) + // subRoot.setupInParent(root, subRootClassDescriptor); + + currentFieldDescriptor.setFieldToComposite(root, subRoot); + return subRoot; + } + /** * Gets the sub root of the object model if its a composite object. Does graph handling Handles * simpl.ref tag to assign an already created instance of the composite object instead of creating diff --git a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/StringPullDeserializer.java b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/StringPullDeserializer.java index 1e71d01f..a55ae2c2 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/StringPullDeserializer.java +++ b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/StringPullDeserializer.java @@ -1,51 +1,51 @@ -package ecologylab.serialization.deserializers.pullhandlers.stringformats; - -import java.io.File; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.DeserializationHookStrategy; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.deserializers.pullhandlers.PullDeserializer; - -public abstract class StringPullDeserializer extends PullDeserializer -{ - - public StringPullDeserializer(SimplTypesScope translationScope, - TranslationContext translationContext) - { - super(translationScope, translationContext); - } - - /** - * Constructs that creates a deserialization handler - * - * @param translationScope - * translation scope to use for de/serializing subsequent char sequences - * @param translationContext - * used for graph handling - */ - public StringPullDeserializer(SimplTypesScope translationScope, - TranslationContext translationContext, DeserializationHookStrategy deserializationHookStrategy) - { - super(translationScope, translationContext, deserializationHookStrategy); - } - - public abstract Object parse(CharSequence charSequence) throws SIMPLTranslationException; - - - protected void SetAllScalarFieldsToDefault(Object context, ClassDescriptor cd, ScalarUnmarshallingContext scalarContext) - { - for(FieldDescriptor fd: cd.allFieldDescriptors()) - { - if(fd.isScalar()) - { - fd.setFieldToScalarDefault(context, scalarContext); - } - } - } -} +package ecologylab.serialization.deserializers.pullhandlers.stringformats; + +import java.io.File; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.DeserializationHookStrategy; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.deserializers.pullhandlers.PullDeserializer; + +public abstract class StringPullDeserializer extends PullDeserializer +{ + + public StringPullDeserializer(SimplTypesScope translationScope, + TranslationContext translationContext) + { + super(translationScope, translationContext); + } + + /** + * Constructs that creates a deserialization handler + * + * @param translationScope + * translation scope to use for de/serializing subsequent char sequences + * @param translationContext + * used for graph handling + */ + public StringPullDeserializer(SimplTypesScope translationScope, + TranslationContext translationContext, DeserializationHookStrategy deserializationHookStrategy) + { + super(translationScope, translationContext, deserializationHookStrategy); + } + + public abstract Object parse(CharSequence charSequence) throws SIMPLTranslationException; + + + protected void SetAllScalarFieldsToDefault(Object context, ClassDescriptor cd, ScalarUnmarshallingContext scalarContext) + { + for(FieldDescriptor fd: cd.allFieldDescriptors()) + { + if(fd.isScalar()) + { + fd.setFieldToScalarDefault(context, scalarContext); + } + } + } +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLPullDeserializer.java b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLPullDeserializer.java index 64e8a3a8..7a056180 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLPullDeserializer.java +++ b/simplCore/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLPullDeserializer.java @@ -205,10 +205,10 @@ private Object parse() throws SIMPLTranslationException, IOException root = rootClassDescriptor.getInstance(); - // Logic to set all field descritpro scalars to defaults. + // Logic to set all field descriptor scalars to defaults. for(FieldDescriptor fd : rootClassDescriptor.allFieldDescriptors()) { - if(fd.isScalar() && (fd.isEnum() == false)) + if(fd.isScalar() && !fd.isCollection() && !fd.isEnum()) { fd.setFieldToScalarDefault(root, translationContext); } @@ -280,7 +280,8 @@ else if (event == XMLParser.END_ELEMENT && currentFieldDescriptor != null && cur String tag = getTagName(); - currentFieldDescriptor = currentFieldDescriptor != null &¤tFieldDescriptor.getType() == FieldType.WRAPPER + currentFieldDescriptor = + currentFieldDescriptor != null &¤tFieldDescriptor.getType() == FieldType.WRAPPER ? currentFieldDescriptor.getWrappedFD() : rootClassDescriptor.getFieldDescriptorByTag(tag, translationScope, null); @@ -578,7 +579,7 @@ private Object getSubRoot(FieldDescriptor currentFieldDescriptor, String tagName { subRoot = subRootClassDescriptor.getInstance(); - // Logic to set all field descritpro scalars to defaults. + // Logic to set all field descriptor scalars to defaults. for(FieldDescriptor fd : subRootClassDescriptor.allFieldDescriptors()) { if(fd.isScalar() && (fd.isEnum() == false)) diff --git a/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateJSONHandler.java b/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateJSONHandler.java index b37a0070..f391e97a 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateJSONHandler.java +++ b/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateJSONHandler.java @@ -1,580 +1,580 @@ -package ecologylab.serialization.deserializers.pushhandlers; - -//import java.io.File; -//import java.io.IOException; -//import java.util.ArrayList; -//import java.util.Collection; -//import java.util.Map; -// -//import org.json.simple.parser.ContentHandler; -//import org.json.simple.parser.JSONParser; -//import org.json.simple.parser.ParseException; -// -//import ecologylab.generic.Debug; -//import ecologylab.net.ParsedURL; -//import ecologylab.serialization.ClassDescriptor; -//import ecologylab.serialization.DeserializationHookStrategy; -//import ecologylab.serialization.ElementState; -//import ecologylab.serialization.FieldDescriptor; -//import ecologylab.serialization.FieldTypes; -//import ecologylab.serialization.RootElementException; -//import ecologylab.serialization.SIMPLTranslationException; -//import ecologylab.serialization.ScalarUnmarshallingContext; -//import ecologylab.serialization.TranslationScope; -//import ecologylab.serialization.types.element.IMappable; - -public class ElementStateJSONHandler // extends Debug implements ContentHandler, FieldTypes, ScalarUnmarshallingContext -{ -// final TranslationScope translationScope; -// -// ElementState root; -// -// ElementState currentElementState; -// -// FieldDescriptor currentFD; -// -// SIMPLTranslationException jsonTranslationException; -// -// ArrayList fdStack = new ArrayList(); -// -// ParsedURL purlContext; -// -// File fileContext; -// -// DeserializationHookStrategy deserializationHookStrategy; -// -// // int numOfCollectionElements = 0; -// -// ArrayList elementsInCollection = new ArrayList(); -// -// public ElementStateJSONHandler(TranslationScope translationScope) -// { -// this.translationScope = translationScope; -// } -// -// public ElementState parse(CharSequence charSequence) -// { -// try -// { -// -// JSONParser parser = new JSONParser(); -// parser.parse(charSequence.toString(), this); -// return root; -// } -// catch (Exception ex) -// { -// ex.printStackTrace(); -// } -// -// return null; -// } -// -// @Override -// public boolean endArray() throws ParseException, IOException -// { -// pop(); -// // numOfCollectionElements = 0; -// return true; -// } -// -// @Override -// public void endJSON() throws ParseException, IOException -// { -// if ((jsonTranslationException == null) && (root != null)) -// root.deserializationPostHook(); -// -// // ElementState.recycleDeserializationMappings(); -// } -// -// @Override -// public boolean endObject() throws ParseException, IOException -// { -// -// return true; -// } -// -// @Override -// public boolean endObjectEntry() throws ParseException, IOException -// { -// if (jsonTranslationException != null) -// return false; -// -// FieldDescriptor currentFD = this.currentFD; -// final int curentFdType = currentFD.getType(); -// -// ElementState currentES = this.currentElementState; -// processPendingScalar(curentFdType, currentES); -// -// final ElementState parentES; -// -// if (currentES.parents == null || currentES.parents.isEmpty()) -// parentES = currentES.parent; -// else -// parentES = currentES.parents.peek(); -// -// switch (curentFdType) -// // every good push deserves a pop :-) (and othertimes, not!) -// { -// case MAP_ELEMENT: -// if (currentES instanceof IMappable) -// { -// final Object key = ((IMappable) currentES).key(); -// Map map = (Map) currentFD.automaticLazyGetCollectionOrMap(parentES); -// // Map map = currentFD.getMap(parentES); -// map.put(key, currentES); -// } -// case COMPOSITE_ELEMENT: -// case COLLECTION_ELEMENT: -// case NAME_SPACE_NESTED_ELEMENT: -// if (parentES != null) -// parentES.createChildHook(currentES); -// else -// debug("cool - post ns element"); -// currentES.deserializationPostHook(); -// if (deserializationHookStrategy != null) -// deserializationHookStrategy.deserializationPostHook(currentES, currentFD); -// this.currentElementState = currentES.parent; -// case NAME_SPACE_SCALAR: -// // case WRAPPER: -// this.currentElementState = parentES; // restore context! -// break; -// default: -// break; -// } -// // end of the Namespace object, so we gotta pop it off, too. -// // if (curentN2JOType == NAME_SPACE_NESTED_ELEMENT) -// // this.currentElementState = this.currentElementState.parent; -// popAndPeekFD(); -// -// if (currentES.parents != null && !currentES.parents.isEmpty() && currentES.parents.size() > 1) -// currentES.parents.pop(); -// -// -// return true; -// } -// -// private void setRoot(ElementState root) -// { -// this.root = root; -// this.currentElementState = root; -// } -// -// private ClassDescriptor currentClassDescriptor() -// { -// if (currentElementState != null) -// return this.currentElementState.classDescriptor(); -// else -// return null; -// } -// -// private void pushFD(FieldDescriptor fd) -// { -// this.fdStack.add(fd); -// } -// -// private void popAndPeekFD() -// { -// ArrayList stack = this.fdStack; -// int last = stack.size() - 1; -// if (last >= 0) -// { -// FieldDescriptor result = stack.remove(last--); -// if (last >= 0) -// result = stack.get(last); -// this.currentFD = result; -// // printStack("After Pop"); -// } -// } -// -// /** -// * Assign pending value to a @simpl_scalar -// * -// * @param curentN2JOType -// * @param currentES -// */ -// private void processPendingScalar(final int curentN2JOType, ElementState currentES) -// { -// final int length = currentTextValue.length(); -// if (length > 0) -// { -// try -// { -// switch (curentN2JOType) -// { -// case NAME_SPACE_SCALAR: -// case SCALAR: -// // TODO -- unmarshall to set field with scalar type -// // copy from the StringBuilder -// String value = stringToDeserializeAsScalar(length); -// currentFD.setFieldToScalar(currentES, value, this); -// break; -// case COLLECTION_SCALAR: -// value = stringToDeserializeAsScalar(length); -// currentFD.addLeafNodeToCollection(currentES, value, this); -// break; -// case COMPOSITE_ELEMENT: -// case COLLECTION_ELEMENT: -// case PSEUDO_FIELD_DESCRIPTOR: -// // TODO - is this code used???? -// // optimizations in currentN2JO are for its parent (they were in scope when it was -// // constructed) -// // so we get the optimizations we need from the currentElementState -// // FIXME -- implement this!!! -// FieldDescriptor scalarTextFD = currentElementState.classDescriptor().getScalarTextFD(); -// if (scalarTextFD != null) -// { -// value = stringToDeserializeAsScalar(length); -// scalarTextFD.setFieldToScalar(currentES, value, this); -// } -// break; -// default: -// break; -// } -// } -// catch (SIMPLTranslationException e) -// { -// this.jsonTranslationException = e; -// } -// -// currentTextValue.setLength(0); -// } -// } -// -// private FieldDescriptor makeIgnoredFieldDescriptor(String key, -// ClassDescriptor currentClassDescriptor) -// { -// FieldDescriptor activeFieldDescriptor; -// currentClassDescriptor.warning(" Ignoring key <" + key + ">"); -// activeFieldDescriptor = new FieldDescriptor(key); // TODO -- should we record -// // declaringClass in here??! -// if (activeFieldDescriptor.getTagName() != null) -// currentClassDescriptor.addFieldDescriptorMapping(activeFieldDescriptor); -// return activeFieldDescriptor; -// } -// -// /** -// * Get the String that will be marshalled into the value with a ScalarType, using the -// * currentTextValue state variable from the parse, and the length parameter. If appropriate, use -// * the currentFD to perform a regex filter on the value before passing it to the appropriate -// * scalar marshalling and field or collection element setter. -// * -// * @param length -// * @return -// */ -// private String stringToDeserializeAsScalar(final int length) -// { -// String result = new String(currentTextValue.substring(0, length)); -// if (translationScope.isPerformFilters()) -// result = currentFD.filterValue(result); -// return result; -// } -// -// void printStack(String msg) -// { -// currentElementState.debug("Stack -- " + msg + "\t[" + this.currentElementState + "]"); -// for (FieldDescriptor thatFD : fdStack) -// { -// println(thatFD.getTagName() + " - 0x" + Integer.toHexString(thatFD.getType())); -// } -// println(""); -// } -// -// StringBuilder currentTextValue = new StringBuilder(1024); -// -// @Override -// public boolean primitive(Object value) throws ParseException, IOException -// { -// if (jsonTranslationException != null) -// return true; -// -// if (currentFD != null) -// { -// int n2joType = currentFD.getType(); -// switch (n2joType) -// { -// case SCALAR: -// case COLLECTION_SCALAR: -// currentTextValue.append(value.toString()); -// processPendingScalar(n2joType, currentElementState); -// // TODO -- unmarshall to set field with scalar type -// break; -// case COMPOSITE_ELEMENT: -// case COLLECTION_ELEMENT: -// case PSEUDO_FIELD_DESCRIPTOR: -// // optimizations in currentN2JO are for its parent (they were in scope when it was -// // constructed) -// // so we get the optimizations we need from the currentElementState -// if (currentElementState.classDescriptor().hasScalarFD()) -// currentTextValue.append(value.toString()); -// break; -// default: -// // TODO ?! can we dump characters in this case, or should we append to textNode?! -// // currentElementState.appendLeafXML(buffy, leafElementName, leafValue, needsEscaping, -// // isCDATA) -// break; -// } -// } -// -// return true; -// } -// -// @Override -// public boolean startArray() throws ParseException, IOException -// { -// push(0); -// return true; -// } -// -// @Override -// public void startJSON() throws ParseException, IOException -// { -// // TODO Auto-generated method stub -// -// } -// -// @Override -// public boolean startObject() throws ParseException, IOException -// { -// // hack to deal with json arrays with list tag outside the array. -// if (currentFD != null) -// if (currentFD.isCollection() && !currentFD.isPolymorphic()) -// { -// if (top() != 0) -// { -// if (currentFD.isWrapped()) -// { -// endObjectEntry(); -// startObjectEntry(currentFD.getCollectionOrMapTagName()); -// } -// else -// { -// FieldDescriptor lastFD = currentFD; -// endObjectEntry(); -// startObjectEntry(lastFD.getCollectionOrMapTagName()); -// } -// } -// incrementTop(); -// // numOfCollectionElements++; -// } -// -// return true; -// } -// -// @Override -// public boolean startObjectEntry(String key) throws ParseException, IOException -// { -// if (jsonTranslationException != null) -// return false; -// -// FieldDescriptor childFD = null; -// final boolean isRoot = (root == null); -// if (isRoot) -// { // form the root ElementState! -// ClassDescriptor rootClassDescriptor = translationScope.getClassDescriptorByTag(key); -// if (rootClassDescriptor != null) -// { -// try -// { -// ElementState root = null; -// if (root == null) -// root = rootClassDescriptor.getInstance(); -// if (root != null) -// { -// root.setupRoot(); -// setRoot(root); -// if (deserializationHookStrategy != null) -// deserializationHookStrategy.deserializationPreHook(root, null); -// -// childFD = rootClassDescriptor.pseudoFieldDescriptor(); -// } -// else -// { -// this.jsonTranslationException = new RootElementException(key, translationScope); -// return false; -// } -// } -// catch (SIMPLTranslationException e) -// { -// jsonTranslationException = e; -// } -// } -// else -// { -// // else, we dont translate this element; we ignore it. -// String message = "JSON Translation WARNING: Cant find class object for Root JSON element <" -// + key + ">: Ignored. "; -// println(message); -// jsonTranslationException = new SIMPLTranslationException(message); -// return false; -// } -// } -// else -// // not root -// { -// final int currentType = currentFD.getType(); -// ElementState currentES = this.currentElementState; -// // if there is a pending text node, assign it somehow! -// processPendingScalar(currentType, currentES); -// -// ClassDescriptor currentClassDescriptor = currentClassDescriptor(); -// childFD = (currentFD != null) && (currentType == IGNORED_ELEMENT) ? -// // new NodeToJavaOptimizations(tagName) : // (nice for debugging; slows us down) -// FieldDescriptor.IGNORED_ELEMENT_FIELD_DESCRIPTOR -// : (currentType == WRAPPER) ? currentFD.getWrappedFD() : currentClassDescriptor -// .getFieldDescriptorByTag(key, translationScope, currentES); -// if (childFD == null) -// { -// childFD = makeIgnoredFieldDescriptor(key, currentClassDescriptor); -// } -// } -// this.currentFD = childFD; -// // TODO? -- do we need to avoid this if null from an exception in translating root? -// pushFD(childFD); -// // printStack("After push"); -// -// if (isRoot) -// return true; -// -// ElementState currentElementState = this.currentElementState; -// ElementState childES = null; -// try -// { -// switch (childFD.getType()) -// { -// case COMPOSITE_ELEMENT: -// childES = childFD.constructChildElementState(currentElementState, key); -// -// if (childES == null) -// { -// childFD = makeIgnoredFieldDescriptor(key, currentClassDescriptor()); -// } -// else -// childFD.setFieldToComposite(currentElementState, childES); -// -// // maybe we -// // should do -// // this on close -// // element -// break; -// case SCALAR: -// // wait for characters to set scalar field -// // activeN2JO.setScalarFieldWithLeafNode(activeES, childNode); -// break; -// case COLLECTION_ELEMENT: -// -// Collection collection = (Collection) childFD -// .automaticLazyGetCollectionOrMap(currentElementState); -// if (collection != null) -// { -// ElementState childElement = childFD.constructChildElementState(currentElementState, key); -// childES = childElement; -// -// if (childES == null) -// { -// childFD = makeIgnoredFieldDescriptor(key, currentClassDescriptor()); -// } -// -// collection.add(childES); -// } -// // activeNJO.formElementAndAddToCollection(activeES, childNode); -// break; -// case COLLECTION_SCALAR: -// // wait for characters to create scalar reference type and add to collection -// // activeN2JO.addLeafNodeToCollection(activeES, childNode); -// break; -// case MAP_ELEMENT: -// Map map = (Map) childFD.automaticLazyGetCollectionOrMap(currentElementState); -// if (map != null) -// { -// ElementState childElement = childFD.constructChildElementState(currentElementState, key); -// -// childES = childElement; -// if (childES == null) -// { -// this.currentFD = makeIgnoredFieldDescriptor(key, currentClassDescriptor()); -// } -// } -// // Map map = activeFieldDescriptor.getMap(currentElementState); -// // if (map != null) -// // { -// // childES = activeFieldDescriptor.constructChildElementState(currentElementState, tagName); -// // } -// break; -// case IGNORED_ELEMENT: -// // should get a set of Optimizations for this, to represent its subfields -// case BAD_FIELD: -// case WRAPPER: -// default: -// break; -// -// } -// if (childES != null) -// { -// // fill in its attributes -// if (deserializationHookStrategy != null) -// deserializationHookStrategy.deserializationPreHook(childES, childFD); -// -// this.currentElementState = childES; // childES.parent = old currentElementState -// this.currentFD = childFD; -// } -// } -// catch (SIMPLTranslationException e) -// { -// this.jsonTranslationException = e; -// } -// -// return true; -// } -// -// /** -// * @return the root -// */ -// public ElementState root() -// { -// return root; -// } -// -// public File fileContext() -// { -// return (fileContext != null) ? fileContext : (purlContext != null) ? purlContext.file() : null; -// } -// -// public ParsedURL purlContext() -// { -// return purlContext; -// } -// -// public Integer pop() -// { -// int num = 0; -// -// if (this.elementsInCollection.size() > 0) -// { -// num = this.elementsInCollection.get(elementsInCollection.size() - 1); -// this.elementsInCollection.remove(elementsInCollection.size() - 1); -// } -// return num; -// } -// -// public void push(Integer num) -// { -// this.elementsInCollection.add(num); -// } -// -// public int top() -// { -// int num = 0; -// -// if (this.elementsInCollection.size() > 0) -// { -// num = this.elementsInCollection.get(elementsInCollection.size() - 1); -// } -// return num; -// } -// -// public void incrementTop() -// { -// int num = pop(); -// push(++num); -// } -} +package ecologylab.serialization.deserializers.pushhandlers; + +//import java.io.File; +//import java.io.IOException; +//import java.util.ArrayList; +//import java.util.Collection; +//import java.util.Map; +// +//import org.json.simple.parser.ContentHandler; +//import org.json.simple.parser.JSONParser; +//import org.json.simple.parser.ParseException; +// +//import ecologylab.generic.Debug; +//import ecologylab.net.ParsedURL; +//import ecologylab.serialization.ClassDescriptor; +//import ecologylab.serialization.DeserializationHookStrategy; +//import ecologylab.serialization.ElementState; +//import ecologylab.serialization.FieldDescriptor; +//import ecologylab.serialization.FieldTypes; +//import ecologylab.serialization.RootElementException; +//import ecologylab.serialization.SIMPLTranslationException; +//import ecologylab.serialization.ScalarUnmarshallingContext; +//import ecologylab.serialization.TranslationScope; +//import ecologylab.serialization.types.element.IMappable; + +public class ElementStateJSONHandler // extends Debug implements ContentHandler, FieldTypes, ScalarUnmarshallingContext +{ +// final TranslationScope translationScope; +// +// ElementState root; +// +// ElementState currentElementState; +// +// FieldDescriptor currentFD; +// +// SIMPLTranslationException jsonTranslationException; +// +// ArrayList fdStack = new ArrayList(); +// +// ParsedURL purlContext; +// +// File fileContext; +// +// DeserializationHookStrategy deserializationHookStrategy; +// +// // int numOfCollectionElements = 0; +// +// ArrayList elementsInCollection = new ArrayList(); +// +// public ElementStateJSONHandler(TranslationScope translationScope) +// { +// this.translationScope = translationScope; +// } +// +// public ElementState parse(CharSequence charSequence) +// { +// try +// { +// +// JSONParser parser = new JSONParser(); +// parser.parse(charSequence.toString(), this); +// return root; +// } +// catch (Exception ex) +// { +// ex.printStackTrace(); +// } +// +// return null; +// } +// +// @Override +// public boolean endArray() throws ParseException, IOException +// { +// pop(); +// // numOfCollectionElements = 0; +// return true; +// } +// +// @Override +// public void endJSON() throws ParseException, IOException +// { +// if ((jsonTranslationException == null) && (root != null)) +// root.deserializationPostHook(); +// +// // ElementState.recycleDeserializationMappings(); +// } +// +// @Override +// public boolean endObject() throws ParseException, IOException +// { +// +// return true; +// } +// +// @Override +// public boolean endObjectEntry() throws ParseException, IOException +// { +// if (jsonTranslationException != null) +// return false; +// +// FieldDescriptor currentFD = this.currentFD; +// final int curentFdType = currentFD.getType(); +// +// ElementState currentES = this.currentElementState; +// processPendingScalar(curentFdType, currentES); +// +// final ElementState parentES; +// +// if (currentES.parents == null || currentES.parents.isEmpty()) +// parentES = currentES.parent; +// else +// parentES = currentES.parents.peek(); +// +// switch (curentFdType) +// // every good push deserves a pop :-) (and othertimes, not!) +// { +// case MAP_ELEMENT: +// if (currentES instanceof IMappable) +// { +// final Object key = ((IMappable) currentES).key(); +// Map map = (Map) currentFD.automaticLazyGetCollectionOrMap(parentES); +// // Map map = currentFD.getMap(parentES); +// map.put(key, currentES); +// } +// case COMPOSITE_ELEMENT: +// case COLLECTION_ELEMENT: +// case NAME_SPACE_NESTED_ELEMENT: +// if (parentES != null) +// parentES.createChildHook(currentES); +// else +// debug("cool - post ns element"); +// currentES.deserializationPostHook(); +// if (deserializationHookStrategy != null) +// deserializationHookStrategy.deserializationPostHook(currentES, currentFD); +// this.currentElementState = currentES.parent; +// case NAME_SPACE_SCALAR: +// // case WRAPPER: +// this.currentElementState = parentES; // restore context! +// break; +// default: +// break; +// } +// // end of the Namespace object, so we gotta pop it off, too. +// // if (curentN2JOType == NAME_SPACE_NESTED_ELEMENT) +// // this.currentElementState = this.currentElementState.parent; +// popAndPeekFD(); +// +// if (currentES.parents != null && !currentES.parents.isEmpty() && currentES.parents.size() > 1) +// currentES.parents.pop(); +// +// +// return true; +// } +// +// private void setRoot(ElementState root) +// { +// this.root = root; +// this.currentElementState = root; +// } +// +// private ClassDescriptor currentClassDescriptor() +// { +// if (currentElementState != null) +// return this.currentElementState.classDescriptor(); +// else +// return null; +// } +// +// private void pushFD(FieldDescriptor fd) +// { +// this.fdStack.add(fd); +// } +// +// private void popAndPeekFD() +// { +// ArrayList stack = this.fdStack; +// int last = stack.size() - 1; +// if (last >= 0) +// { +// FieldDescriptor result = stack.remove(last--); +// if (last >= 0) +// result = stack.get(last); +// this.currentFD = result; +// // printStack("After Pop"); +// } +// } +// +// /** +// * Assign pending value to a @simpl_scalar +// * +// * @param curentN2JOType +// * @param currentES +// */ +// private void processPendingScalar(final int curentN2JOType, ElementState currentES) +// { +// final int length = currentTextValue.length(); +// if (length > 0) +// { +// try +// { +// switch (curentN2JOType) +// { +// case NAME_SPACE_SCALAR: +// case SCALAR: +// // TODO -- unmarshall to set field with scalar type +// // copy from the StringBuilder +// String value = stringToDeserializeAsScalar(length); +// currentFD.setFieldToScalar(currentES, value, this); +// break; +// case COLLECTION_SCALAR: +// value = stringToDeserializeAsScalar(length); +// currentFD.addLeafNodeToCollection(currentES, value, this); +// break; +// case COMPOSITE_ELEMENT: +// case COLLECTION_ELEMENT: +// case PSEUDO_FIELD_DESCRIPTOR: +// // TODO - is this code used???? +// // optimizations in currentN2JO are for its parent (they were in scope when it was +// // constructed) +// // so we get the optimizations we need from the currentElementState +// // FIXME -- implement this!!! +// FieldDescriptor scalarTextFD = currentElementState.classDescriptor().getScalarTextFD(); +// if (scalarTextFD != null) +// { +// value = stringToDeserializeAsScalar(length); +// scalarTextFD.setFieldToScalar(currentES, value, this); +// } +// break; +// default: +// break; +// } +// } +// catch (SIMPLTranslationException e) +// { +// this.jsonTranslationException = e; +// } +// +// currentTextValue.setLength(0); +// } +// } +// +// private FieldDescriptor makeIgnoredFieldDescriptor(String key, +// ClassDescriptor currentClassDescriptor) +// { +// FieldDescriptor activeFieldDescriptor; +// currentClassDescriptor.warning(" Ignoring key <" + key + ">"); +// activeFieldDescriptor = new FieldDescriptor(key); // TODO -- should we record +// // declaringClass in here??! +// if (activeFieldDescriptor.getTagName() != null) +// currentClassDescriptor.addFieldDescriptorMapping(activeFieldDescriptor); +// return activeFieldDescriptor; +// } +// +// /** +// * Get the String that will be marshalled into the value with a ScalarType, using the +// * currentTextValue state variable from the parse, and the length parameter. If appropriate, use +// * the currentFD to perform a regex filter on the value before passing it to the appropriate +// * scalar marshalling and field or collection element setter. +// * +// * @param length +// * @return +// */ +// private String stringToDeserializeAsScalar(final int length) +// { +// String result = new String(currentTextValue.substring(0, length)); +// if (translationScope.isPerformFilters()) +// result = currentFD.filterValue(result); +// return result; +// } +// +// void printStack(String msg) +// { +// currentElementState.debug("Stack -- " + msg + "\t[" + this.currentElementState + "]"); +// for (FieldDescriptor thatFD : fdStack) +// { +// println(thatFD.getTagName() + " - 0x" + Integer.toHexString(thatFD.getType())); +// } +// println(""); +// } +// +// StringBuilder currentTextValue = new StringBuilder(1024); +// +// @Override +// public boolean primitive(Object value) throws ParseException, IOException +// { +// if (jsonTranslationException != null) +// return true; +// +// if (currentFD != null) +// { +// int n2joType = currentFD.getType(); +// switch (n2joType) +// { +// case SCALAR: +// case COLLECTION_SCALAR: +// currentTextValue.append(value.toString()); +// processPendingScalar(n2joType, currentElementState); +// // TODO -- unmarshall to set field with scalar type +// break; +// case COMPOSITE_ELEMENT: +// case COLLECTION_ELEMENT: +// case PSEUDO_FIELD_DESCRIPTOR: +// // optimizations in currentN2JO are for its parent (they were in scope when it was +// // constructed) +// // so we get the optimizations we need from the currentElementState +// if (currentElementState.classDescriptor().hasScalarFD()) +// currentTextValue.append(value.toString()); +// break; +// default: +// // TODO ?! can we dump characters in this case, or should we append to textNode?! +// // currentElementState.appendLeafXML(buffy, leafElementName, leafValue, needsEscaping, +// // isCDATA) +// break; +// } +// } +// +// return true; +// } +// +// @Override +// public boolean startArray() throws ParseException, IOException +// { +// push(0); +// return true; +// } +// +// @Override +// public void startJSON() throws ParseException, IOException +// { +// // TODO Auto-generated method stub +// +// } +// +// @Override +// public boolean startObject() throws ParseException, IOException +// { +// // hack to deal with json arrays with list tag outside the array. +// if (currentFD != null) +// if (currentFD.isCollection() && !currentFD.isPolymorphic()) +// { +// if (top() != 0) +// { +// if (currentFD.isWrapped()) +// { +// endObjectEntry(); +// startObjectEntry(currentFD.getCollectionOrMapTagName()); +// } +// else +// { +// FieldDescriptor lastFD = currentFD; +// endObjectEntry(); +// startObjectEntry(lastFD.getCollectionOrMapTagName()); +// } +// } +// incrementTop(); +// // numOfCollectionElements++; +// } +// +// return true; +// } +// +// @Override +// public boolean startObjectEntry(String key) throws ParseException, IOException +// { +// if (jsonTranslationException != null) +// return false; +// +// FieldDescriptor childFD = null; +// final boolean isRoot = (root == null); +// if (isRoot) +// { // form the root ElementState! +// ClassDescriptor rootClassDescriptor = translationScope.getClassDescriptorByTag(key); +// if (rootClassDescriptor != null) +// { +// try +// { +// ElementState root = null; +// if (root == null) +// root = rootClassDescriptor.getInstance(); +// if (root != null) +// { +// root.setupRoot(); +// setRoot(root); +// if (deserializationHookStrategy != null) +// deserializationHookStrategy.deserializationPreHook(root, null); +// +// childFD = rootClassDescriptor.pseudoFieldDescriptor(); +// } +// else +// { +// this.jsonTranslationException = new RootElementException(key, translationScope); +// return false; +// } +// } +// catch (SIMPLTranslationException e) +// { +// jsonTranslationException = e; +// } +// } +// else +// { +// // else, we dont translate this element; we ignore it. +// String message = "JSON Translation WARNING: Cant find class object for Root JSON element <" +// + key + ">: Ignored. "; +// println(message); +// jsonTranslationException = new SIMPLTranslationException(message); +// return false; +// } +// } +// else +// // not root +// { +// final int currentType = currentFD.getType(); +// ElementState currentES = this.currentElementState; +// // if there is a pending text node, assign it somehow! +// processPendingScalar(currentType, currentES); +// +// ClassDescriptor currentClassDescriptor = currentClassDescriptor(); +// childFD = (currentFD != null) && (currentType == IGNORED_ELEMENT) ? +// // new NodeToJavaOptimizations(tagName) : // (nice for debugging; slows us down) +// FieldDescriptor.IGNORED_ELEMENT_FIELD_DESCRIPTOR +// : (currentType == WRAPPER) ? currentFD.getWrappedFD() : currentClassDescriptor +// .getFieldDescriptorByTag(key, translationScope, currentES); +// if (childFD == null) +// { +// childFD = makeIgnoredFieldDescriptor(key, currentClassDescriptor); +// } +// } +// this.currentFD = childFD; +// // TODO? -- do we need to avoid this if null from an exception in translating root? +// pushFD(childFD); +// // printStack("After push"); +// +// if (isRoot) +// return true; +// +// ElementState currentElementState = this.currentElementState; +// ElementState childES = null; +// try +// { +// switch (childFD.getType()) +// { +// case COMPOSITE_ELEMENT: +// childES = childFD.constructChildElementState(currentElementState, key); +// +// if (childES == null) +// { +// childFD = makeIgnoredFieldDescriptor(key, currentClassDescriptor()); +// } +// else +// childFD.setFieldToComposite(currentElementState, childES); +// +// // maybe we +// // should do +// // this on close +// // element +// break; +// case SCALAR: +// // wait for characters to set scalar field +// // activeN2JO.setScalarFieldWithLeafNode(activeES, childNode); +// break; +// case COLLECTION_ELEMENT: +// +// Collection collection = (Collection) childFD +// .automaticLazyGetCollectionOrMap(currentElementState); +// if (collection != null) +// { +// ElementState childElement = childFD.constructChildElementState(currentElementState, key); +// childES = childElement; +// +// if (childES == null) +// { +// childFD = makeIgnoredFieldDescriptor(key, currentClassDescriptor()); +// } +// +// collection.add(childES); +// } +// // activeNJO.formElementAndAddToCollection(activeES, childNode); +// break; +// case COLLECTION_SCALAR: +// // wait for characters to create scalar reference type and add to collection +// // activeN2JO.addLeafNodeToCollection(activeES, childNode); +// break; +// case MAP_ELEMENT: +// Map map = (Map) childFD.automaticLazyGetCollectionOrMap(currentElementState); +// if (map != null) +// { +// ElementState childElement = childFD.constructChildElementState(currentElementState, key); +// +// childES = childElement; +// if (childES == null) +// { +// this.currentFD = makeIgnoredFieldDescriptor(key, currentClassDescriptor()); +// } +// } +// // Map map = activeFieldDescriptor.getMap(currentElementState); +// // if (map != null) +// // { +// // childES = activeFieldDescriptor.constructChildElementState(currentElementState, tagName); +// // } +// break; +// case IGNORED_ELEMENT: +// // should get a set of Optimizations for this, to represent its subfields +// case BAD_FIELD: +// case WRAPPER: +// default: +// break; +// +// } +// if (childES != null) +// { +// // fill in its attributes +// if (deserializationHookStrategy != null) +// deserializationHookStrategy.deserializationPreHook(childES, childFD); +// +// this.currentElementState = childES; // childES.parent = old currentElementState +// this.currentFD = childFD; +// } +// } +// catch (SIMPLTranslationException e) +// { +// this.jsonTranslationException = e; +// } +// +// return true; +// } +// +// /** +// * @return the root +// */ +// public ElementState root() +// { +// return root; +// } +// +// public File fileContext() +// { +// return (fileContext != null) ? fileContext : (purlContext != null) ? purlContext.file() : null; +// } +// +// public ParsedURL purlContext() +// { +// return purlContext; +// } +// +// public Integer pop() +// { +// int num = 0; +// +// if (this.elementsInCollection.size() > 0) +// { +// num = this.elementsInCollection.get(elementsInCollection.size() - 1); +// this.elementsInCollection.remove(elementsInCollection.size() - 1); +// } +// return num; +// } +// +// public void push(Integer num) +// { +// this.elementsInCollection.add(num); +// } +// +// public int top() +// { +// int num = 0; +// +// if (this.elementsInCollection.size() > 0) +// { +// num = this.elementsInCollection.get(elementsInCollection.size() - 1); +// } +// return num; +// } +// +// public void incrementTop() +// { +// int num = pop(); +// push(++num); +// } +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateJSONPushHandler.java b/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateJSONPushHandler.java index 071b1f92..f3b0228d 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateJSONPushHandler.java +++ b/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateJSONPushHandler.java @@ -1,387 +1,387 @@ -package ecologylab.serialization.deserializers.pushhandlers; -// -//import java.io.File; -//import java.io.IOException; -//import java.util.Collection; -//import java.util.Map; -// -//import org.codehaus.jackson.JsonFactory; -//import org.codehaus.jackson.JsonParseException; -//import org.codehaus.jackson.JsonParser; -//import org.codehaus.jackson.JsonToken; -// -//import ecologylab.generic.Debug; -//import ecologylab.net.ParsedURL; -//import ecologylab.serialization.ClassDescriptor; -//import ecologylab.serialization.DeserializationHookStrategy; -//import ecologylab.serialization.ElementState; -//import ecologylab.serialization.FieldDescriptor; -//import ecologylab.serialization.FieldTypes; -//import ecologylab.serialization.SIMPLTranslationException; -//import ecologylab.serialization.ScalarUnmarshallingContext; -//import ecologylab.serialization.TranslationContext; -//import ecologylab.serialization.TranslationScope; -//import ecologylab.serialization.types.element.IMappable; -// -///** -// * JSON deserialization handler class. Uses the push API for parsing the input JSON docuemets. -// * -// * @author nabeelshahzad -// * -// */ -public class ElementStateJSONPushHandler // extends Debug implements ScalarUnmarshallingContext, FieldTypes -{ -// -// TranslationScope translationScope; -// -// TranslationContext translationContext; -// -// /** -// * JsonParser object from the Jackson JSON parsing library. Implements a push API for parsing JSON -// */ -// JsonParser jp = null; -// -// DeserializationHookStrategy deserializationHookStrategy; -// -// /** -// * Constructs that creates a JSON deserialization handler -// * -// * @param translationScope -// * translation scope to use for de/serializing subsequent char sequences -// * @param translationContext -// * used for graph handling -// */ -// public ElementStateJSONPushHandler(TranslationScope translationScope, -// TranslationContext translationContext) -// { -// this.translationScope = translationScope; -// this.translationContext = translationContext; -// this.deserializationHookStrategy = null; -// } -// -// /** -// * Constructs that creates a JSON deserialization handler -// * -// * @param translationScope -// * translation scope to use for de/serializing subsequent char sequences -// * @param translationContext -// * used for graph handling -// */ -// public ElementStateJSONPushHandler(TranslationScope translationScope, -// TranslationContext translationContext, DeserializationHookStrategy deserializationHookStrategy) -// { -// this.translationScope = translationScope; -// this.translationContext = translationContext; -// this.deserializationHookStrategy = deserializationHookStrategy; -// } -// -// /** -// * The main parse method accepts a CharSequence and creates a corresponding object model. Sets up -// * the root object and creates instances of the root object before calling a recursive method that -// * creates the complete object model -// * -// * @param charSequence -// * @return -// * @throws JsonParseException -// * @throws IOException -// * @throws SIMPLTranslationException -// */ -// public ElementState parse(CharSequence charSequence) -// { -// -// try -// { -// // configure the json parser -// JsonFactory f = new JsonFactory(); -// jp = f.createJsonParser(charSequence.toString()); -// -// // all JSON documents start with an opening brace. -// if (jp.nextToken() != JsonToken.START_OBJECT) -// { -// println("JSON Translation ERROR: not a valid JSON object. It should start with {"); -// } -// -// // move the first field in the document. typically it is the root element. -// jp.nextToken(); -// -// ElementState root = null; -// -// // find the classdescriptor for the root element. -// ClassDescriptor rootClassDescriptor = translationScope.getClassDescriptorByTag(jp -// .getCurrentName()); -// -// root = rootClassDescriptor.getInstance(); -// root.setupRoot(); -// root.deserializationPreHook(); -// if (deserializationHookStrategy != null) -// deserializationHookStrategy.deserializationPreHook(root, null); -// -// // move to the first field of the root element. -// jp.nextToken(); -// jp.nextToken(); -// -// // complete the object model from root and recursively of the fields it is composed of -// createObjectModel(root, rootClassDescriptor); -// -// return root; -// } -// catch (Exception ex) -// { -// ex.printStackTrace(); -// } -// -// return null; -// } -// -// /** -// * Recursive method that moves forward in the CharSequence through JsonParser to create a -// * corresponding object model -// * -// * @param root -// * instance of the root element created by the calling method -// * @param rootClassDescriptor -// * instance of the classdescriptor of the root element created by the calling method -// * @throws JsonParseException -// * @throws IOException -// * @throws SIMPLTranslationException -// */ -// private void createObjectModel(ElementState root, ClassDescriptor rootClassDescriptor) -// throws JsonParseException, IOException, SIMPLTranslationException -// { -// FieldDescriptor currentFieldDescriptor = null; -// ElementState subRoot = null; -// -// // iterate through each element of the current composite element. -// while (jp.getCurrentToken() != JsonToken.END_OBJECT) -// { -// if (!handleSimplId(jp.getText(), root)) -// { -// currentFieldDescriptor = (currentFieldDescriptor != null) -// && (currentFieldDescriptor.getType() == IGNORED_ELEMENT) ? FieldDescriptor.IGNORED_ELEMENT_FIELD_DESCRIPTOR -// : (currentFieldDescriptor != null && currentFieldDescriptor.getType() == WRAPPER) ? currentFieldDescriptor -// .getWrappedFD() -// : rootClassDescriptor.getFieldDescriptorByTag(jp.getText(), translationScope, null); -// -// int fieldType = currentFieldDescriptor.getType(); -// -// switch (fieldType) -// { -// case SCALAR: -// jp.nextToken(); -// currentFieldDescriptor.setFieldToScalar(root, jp.getText(), this); -// break; -// case COMPOSITE_ELEMENT: -// jp.nextToken(); -// -// String tagName = jp.getCurrentName(); -// subRoot = getSubRoot(currentFieldDescriptor, tagName); -// -// ClassDescriptor subRootClassDescriptor = currentFieldDescriptor -// .getChildClassDescriptor(tagName); -// -// if (subRoot != null) -// subRoot.setupInParent(root, subRootClassDescriptor); -// -// currentFieldDescriptor.setFieldToComposite(root, subRoot); -// break; -// case COLLECTION_ELEMENT: -// jp.nextToken(); -// if (currentFieldDescriptor.isPolymorphic()) -// { -// // ignore the wrapper tag -// if (!currentFieldDescriptor.isWrapped()) -// jp.nextToken(); -// -// while (jp.getCurrentToken() != JsonToken.END_ARRAY) -// { -// jp.nextToken(); -// jp.nextToken(); -// -// subRoot = getSubRoot(currentFieldDescriptor, jp.getCurrentName()); -// Collection collection = (Collection) currentFieldDescriptor -// .automaticLazyGetCollectionOrMap(root); -// collection.add(subRoot); -// -// jp.nextToken(); -// jp.nextToken(); -// } -// -// } -// else -// { -// while (jp.nextToken() != JsonToken.END_ARRAY) -// { -// subRoot = getSubRoot(currentFieldDescriptor, jp.getCurrentName()); -// Collection collection = (Collection) currentFieldDescriptor -// .automaticLazyGetCollectionOrMap(root); -// collection.add(subRoot); -// } -// } -// break; -// case MAP_ELEMENT: -// jp.nextToken(); -// if (currentFieldDescriptor.isPolymorphic()) -// { -// -// // ignore the wrapper tag -// if (!currentFieldDescriptor.isWrapped()) -// jp.nextToken(); -// -// while (jp.getCurrentToken() != JsonToken.END_ARRAY) -// { -// jp.nextToken(); -// jp.nextToken(); -// -// subRoot = getSubRoot(currentFieldDescriptor, jp.getCurrentName()); -// if (subRoot instanceof IMappable) -// { -// final Object key = ((IMappable) subRoot).key(); -// Map map = (Map) currentFieldDescriptor.automaticLazyGetCollectionOrMap(root); -// map.put(key, subRoot); -// } -// -// jp.nextToken(); -// jp.nextToken(); -// } -// -// } -// else -// { -// while (jp.nextToken() != JsonToken.END_ARRAY) -// { -// subRoot = getSubRoot(currentFieldDescriptor, jp.getCurrentName()); -// if (subRoot instanceof IMappable) -// { -// final Object key = ((IMappable) subRoot).key(); -// Map map = (Map) currentFieldDescriptor.automaticLazyGetCollectionOrMap(root); -// map.put(key, subRoot); -// } -// } -// } -// break; -// case COLLECTION_SCALAR: -// jp.nextToken(); -// while (jp.nextToken() != JsonToken.END_ARRAY) -// { -// currentFieldDescriptor.addLeafNodeToCollection(root, jp.getText(), this); -// } -// break; -// case WRAPPER: -// if (!currentFieldDescriptor.getWrappedFD().isPolymorphic()) -// jp.nextToken(); -// break; -// } -// } -// -// jp.nextToken(); -// } -// -// root.deserializationPostHook(); -// if (deserializationHookStrategy != null) -// deserializationHookStrategy.deserializationPostHook(root, currentFieldDescriptor); -// } -// -// /** -// * Gets the sub root of the object model if its a composite object. Does graph handling Handles -// * simpl.ref tag to assign an already created instance of the composite object instead of creating -// * a new one -// * -// * @param currentFieldDescriptor -// * @return -// * @throws SIMPLTranslationException -// * @throws JsonParseException -// * @throws IOException -// */ -// private ElementState getSubRoot(FieldDescriptor currentFieldDescriptor, String tagName) -// throws SIMPLTranslationException, JsonParseException, IOException -// { -// jp.nextToken(); -// -// ElementState subRoot = null; -// -// if (jp.getCurrentToken() == JsonToken.FIELD_NAME) -// { -// // check for simpl.ref if exists that we need an already created instance, instead of creating -// // a new one. -// if (jp.getText().equals(TranslationContext.JSON_SIMPL_REF)) -// { -// jp.nextToken(); -// subRoot = translationContext.getFromMap(jp.getText()); -// jp.nextToken(); -// } -// else -// { -// ClassDescriptor subRootClassDescriptor = currentFieldDescriptor -// .getChildClassDescriptor(tagName); -// -// if (subRootClassDescriptor == null) -// { -// System.out.println("*************************** "); -// System.out.println(tagName + " TAG NOT FOUND"); -// jp.nextToken(); -// System.out.println(jp.getText()); -// jp.nextToken(); -// System.out.println(jp.getText()); -// jp.nextToken(); -// System.out.println(jp.getText()); -// jp.nextToken(); -// System.out.println(jp.getText()); -// jp.nextToken(); -// System.out.println(jp.getText()); -// jp.nextToken(); -// System.out.println(jp.getText()); -// jp.nextToken(); -// System.out.println(jp.getText()); -// jp.nextToken(); -// System.out.println(jp.getText()); -// jp.nextToken(); -// System.out.println(jp.getText()); -// System.out.println("*************************** "); -// } -// -// subRoot = subRootClassDescriptor.getInstance(); -// -// createObjectModel(subRoot, subRootClassDescriptor); -// } -// } -// -// return subRoot; -// } -// -// /** -// * Function used for handling graph's simpl.id tag. If the tag is present the current ElementState -// * object is marked as unmarshalled. Therefore, later simpl.ref can be used to extract this -// * instance -// * -// * @param tagName -// * @param root -// * @return -// * @throws JsonParseException -// * @throws IOException -// */ -// private boolean handleSimplId(String tagName, ElementState root) throws JsonParseException, -// IOException -// { -// if (tagName.equals(TranslationContext.JSON_SIMPL_ID)) -// { -// jp.nextToken(); -// translationContext.markAsUnmarshalled(jp.getText(), root); -// return true; -// } -// return false; -// } -// -// @Override -// public File fileContext() -// { -// // TODO Auto-generated method stub -// return null; -// } -// -// @Override -// public ParsedURL purlContext() -// { -// // TODO Auto-generated method stub -// return null; -// } -} +package ecologylab.serialization.deserializers.pushhandlers; +// +//import java.io.File; +//import java.io.IOException; +//import java.util.Collection; +//import java.util.Map; +// +//import org.codehaus.jackson.JsonFactory; +//import org.codehaus.jackson.JsonParseException; +//import org.codehaus.jackson.JsonParser; +//import org.codehaus.jackson.JsonToken; +// +//import ecologylab.generic.Debug; +//import ecologylab.net.ParsedURL; +//import ecologylab.serialization.ClassDescriptor; +//import ecologylab.serialization.DeserializationHookStrategy; +//import ecologylab.serialization.ElementState; +//import ecologylab.serialization.FieldDescriptor; +//import ecologylab.serialization.FieldTypes; +//import ecologylab.serialization.SIMPLTranslationException; +//import ecologylab.serialization.ScalarUnmarshallingContext; +//import ecologylab.serialization.TranslationContext; +//import ecologylab.serialization.TranslationScope; +//import ecologylab.serialization.types.element.IMappable; +// +///** +// * JSON deserialization handler class. Uses the push API for parsing the input JSON docuemets. +// * +// * @author nabeelshahzad +// * +// */ +public class ElementStateJSONPushHandler // extends Debug implements ScalarUnmarshallingContext, FieldTypes +{ +// +// TranslationScope translationScope; +// +// TranslationContext translationContext; +// +// /** +// * JsonParser object from the Jackson JSON parsing library. Implements a push API for parsing JSON +// */ +// JsonParser jp = null; +// +// DeserializationHookStrategy deserializationHookStrategy; +// +// /** +// * Constructs that creates a JSON deserialization handler +// * +// * @param translationScope +// * translation scope to use for de/serializing subsequent char sequences +// * @param translationContext +// * used for graph handling +// */ +// public ElementStateJSONPushHandler(TranslationScope translationScope, +// TranslationContext translationContext) +// { +// this.translationScope = translationScope; +// this.translationContext = translationContext; +// this.deserializationHookStrategy = null; +// } +// +// /** +// * Constructs that creates a JSON deserialization handler +// * +// * @param translationScope +// * translation scope to use for de/serializing subsequent char sequences +// * @param translationContext +// * used for graph handling +// */ +// public ElementStateJSONPushHandler(TranslationScope translationScope, +// TranslationContext translationContext, DeserializationHookStrategy deserializationHookStrategy) +// { +// this.translationScope = translationScope; +// this.translationContext = translationContext; +// this.deserializationHookStrategy = deserializationHookStrategy; +// } +// +// /** +// * The main parse method accepts a CharSequence and creates a corresponding object model. Sets up +// * the root object and creates instances of the root object before calling a recursive method that +// * creates the complete object model +// * +// * @param charSequence +// * @return +// * @throws JsonParseException +// * @throws IOException +// * @throws SIMPLTranslationException +// */ +// public ElementState parse(CharSequence charSequence) +// { +// +// try +// { +// // configure the json parser +// JsonFactory f = new JsonFactory(); +// jp = f.createJsonParser(charSequence.toString()); +// +// // all JSON documents start with an opening brace. +// if (jp.nextToken() != JsonToken.START_OBJECT) +// { +// println("JSON Translation ERROR: not a valid JSON object. It should start with {"); +// } +// +// // move the first field in the document. typically it is the root element. +// jp.nextToken(); +// +// ElementState root = null; +// +// // find the classdescriptor for the root element. +// ClassDescriptor rootClassDescriptor = translationScope.getClassDescriptorByTag(jp +// .getCurrentName()); +// +// root = rootClassDescriptor.getInstance(); +// root.setupRoot(); +// root.deserializationPreHook(); +// if (deserializationHookStrategy != null) +// deserializationHookStrategy.deserializationPreHook(root, null); +// +// // move to the first field of the root element. +// jp.nextToken(); +// jp.nextToken(); +// +// // complete the object model from root and recursively of the fields it is composed of +// createObjectModel(root, rootClassDescriptor); +// +// return root; +// } +// catch (Exception ex) +// { +// ex.printStackTrace(); +// } +// +// return null; +// } +// +// /** +// * Recursive method that moves forward in the CharSequence through JsonParser to create a +// * corresponding object model +// * +// * @param root +// * instance of the root element created by the calling method +// * @param rootClassDescriptor +// * instance of the classdescriptor of the root element created by the calling method +// * @throws JsonParseException +// * @throws IOException +// * @throws SIMPLTranslationException +// */ +// private void createObjectModel(ElementState root, ClassDescriptor rootClassDescriptor) +// throws JsonParseException, IOException, SIMPLTranslationException +// { +// FieldDescriptor currentFieldDescriptor = null; +// ElementState subRoot = null; +// +// // iterate through each element of the current composite element. +// while (jp.getCurrentToken() != JsonToken.END_OBJECT) +// { +// if (!handleSimplId(jp.getText(), root)) +// { +// currentFieldDescriptor = (currentFieldDescriptor != null) +// && (currentFieldDescriptor.getType() == IGNORED_ELEMENT) ? FieldDescriptor.IGNORED_ELEMENT_FIELD_DESCRIPTOR +// : (currentFieldDescriptor != null && currentFieldDescriptor.getType() == WRAPPER) ? currentFieldDescriptor +// .getWrappedFD() +// : rootClassDescriptor.getFieldDescriptorByTag(jp.getText(), translationScope, null); +// +// int fieldType = currentFieldDescriptor.getType(); +// +// switch (fieldType) +// { +// case SCALAR: +// jp.nextToken(); +// currentFieldDescriptor.setFieldToScalar(root, jp.getText(), this); +// break; +// case COMPOSITE_ELEMENT: +// jp.nextToken(); +// +// String tagName = jp.getCurrentName(); +// subRoot = getSubRoot(currentFieldDescriptor, tagName); +// +// ClassDescriptor subRootClassDescriptor = currentFieldDescriptor +// .getChildClassDescriptor(tagName); +// +// if (subRoot != null) +// subRoot.setupInParent(root, subRootClassDescriptor); +// +// currentFieldDescriptor.setFieldToComposite(root, subRoot); +// break; +// case COLLECTION_ELEMENT: +// jp.nextToken(); +// if (currentFieldDescriptor.isPolymorphic()) +// { +// // ignore the wrapper tag +// if (!currentFieldDescriptor.isWrapped()) +// jp.nextToken(); +// +// while (jp.getCurrentToken() != JsonToken.END_ARRAY) +// { +// jp.nextToken(); +// jp.nextToken(); +// +// subRoot = getSubRoot(currentFieldDescriptor, jp.getCurrentName()); +// Collection collection = (Collection) currentFieldDescriptor +// .automaticLazyGetCollectionOrMap(root); +// collection.add(subRoot); +// +// jp.nextToken(); +// jp.nextToken(); +// } +// +// } +// else +// { +// while (jp.nextToken() != JsonToken.END_ARRAY) +// { +// subRoot = getSubRoot(currentFieldDescriptor, jp.getCurrentName()); +// Collection collection = (Collection) currentFieldDescriptor +// .automaticLazyGetCollectionOrMap(root); +// collection.add(subRoot); +// } +// } +// break; +// case MAP_ELEMENT: +// jp.nextToken(); +// if (currentFieldDescriptor.isPolymorphic()) +// { +// +// // ignore the wrapper tag +// if (!currentFieldDescriptor.isWrapped()) +// jp.nextToken(); +// +// while (jp.getCurrentToken() != JsonToken.END_ARRAY) +// { +// jp.nextToken(); +// jp.nextToken(); +// +// subRoot = getSubRoot(currentFieldDescriptor, jp.getCurrentName()); +// if (subRoot instanceof IMappable) +// { +// final Object key = ((IMappable) subRoot).key(); +// Map map = (Map) currentFieldDescriptor.automaticLazyGetCollectionOrMap(root); +// map.put(key, subRoot); +// } +// +// jp.nextToken(); +// jp.nextToken(); +// } +// +// } +// else +// { +// while (jp.nextToken() != JsonToken.END_ARRAY) +// { +// subRoot = getSubRoot(currentFieldDescriptor, jp.getCurrentName()); +// if (subRoot instanceof IMappable) +// { +// final Object key = ((IMappable) subRoot).key(); +// Map map = (Map) currentFieldDescriptor.automaticLazyGetCollectionOrMap(root); +// map.put(key, subRoot); +// } +// } +// } +// break; +// case COLLECTION_SCALAR: +// jp.nextToken(); +// while (jp.nextToken() != JsonToken.END_ARRAY) +// { +// currentFieldDescriptor.addLeafNodeToCollection(root, jp.getText(), this); +// } +// break; +// case WRAPPER: +// if (!currentFieldDescriptor.getWrappedFD().isPolymorphic()) +// jp.nextToken(); +// break; +// } +// } +// +// jp.nextToken(); +// } +// +// root.deserializationPostHook(); +// if (deserializationHookStrategy != null) +// deserializationHookStrategy.deserializationPostHook(root, currentFieldDescriptor); +// } +// +// /** +// * Gets the sub root of the object model if its a composite object. Does graph handling Handles +// * simpl.ref tag to assign an already created instance of the composite object instead of creating +// * a new one +// * +// * @param currentFieldDescriptor +// * @return +// * @throws SIMPLTranslationException +// * @throws JsonParseException +// * @throws IOException +// */ +// private ElementState getSubRoot(FieldDescriptor currentFieldDescriptor, String tagName) +// throws SIMPLTranslationException, JsonParseException, IOException +// { +// jp.nextToken(); +// +// ElementState subRoot = null; +// +// if (jp.getCurrentToken() == JsonToken.FIELD_NAME) +// { +// // check for simpl.ref if exists that we need an already created instance, instead of creating +// // a new one. +// if (jp.getText().equals(TranslationContext.JSON_SIMPL_REF)) +// { +// jp.nextToken(); +// subRoot = translationContext.getFromMap(jp.getText()); +// jp.nextToken(); +// } +// else +// { +// ClassDescriptor subRootClassDescriptor = currentFieldDescriptor +// .getChildClassDescriptor(tagName); +// +// if (subRootClassDescriptor == null) +// { +// System.out.println("*************************** "); +// System.out.println(tagName + " TAG NOT FOUND"); +// jp.nextToken(); +// System.out.println(jp.getText()); +// jp.nextToken(); +// System.out.println(jp.getText()); +// jp.nextToken(); +// System.out.println(jp.getText()); +// jp.nextToken(); +// System.out.println(jp.getText()); +// jp.nextToken(); +// System.out.println(jp.getText()); +// jp.nextToken(); +// System.out.println(jp.getText()); +// jp.nextToken(); +// System.out.println(jp.getText()); +// jp.nextToken(); +// System.out.println(jp.getText()); +// jp.nextToken(); +// System.out.println(jp.getText()); +// System.out.println("*************************** "); +// } +// +// subRoot = subRootClassDescriptor.getInstance(); +// +// createObjectModel(subRoot, subRootClassDescriptor); +// } +// } +// +// return subRoot; +// } +// +// /** +// * Function used for handling graph's simpl.id tag. If the tag is present the current ElementState +// * object is marked as unmarshalled. Therefore, later simpl.ref can be used to extract this +// * instance +// * +// * @param tagName +// * @param root +// * @return +// * @throws JsonParseException +// * @throws IOException +// */ +// private boolean handleSimplId(String tagName, ElementState root) throws JsonParseException, +// IOException +// { +// if (tagName.equals(TranslationContext.JSON_SIMPL_ID)) +// { +// jp.nextToken(); +// translationContext.markAsUnmarshalled(jp.getText(), root); +// return true; +// } +// return false; +// } +// +// @Override +// public File fileContext() +// { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public ParsedURL purlContext() +// { +// // TODO Auto-generated method stub +// return null; +// } +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateSAXHandler.java b/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateSAXHandler.java index 312a7d18..e5706191 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateSAXHandler.java +++ b/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateSAXHandler.java @@ -1,1025 +1,1025 @@ -///** -// * -// */ -package ecologylab.serialization.deserializers.pushhandlers; -// -//import java.io.BufferedInputStream; -//import java.io.File; -//import java.io.FileInputStream; -//import java.io.FileNotFoundException; -//import java.io.IOException; -//import java.io.InputStream; -//import java.io.Reader; -//import java.io.StringReader; -//import java.net.URL; -//import java.util.ArrayList; -//import java.util.Collection; -//import java.util.Map; -// -//import org.xml.sax.Attributes; -//import org.xml.sax.ContentHandler; -//import org.xml.sax.InputSource; -//import org.xml.sax.Locator; -//import org.xml.sax.SAXException; -//import org.xml.sax.XMLReader; -//import org.xml.sax.helpers.XMLReaderFactory; -// -//import ecologylab.generic.Debug; -//import ecologylab.generic.ReflectionTools; -//import ecologylab.generic.StringInputStream; -//import ecologylab.net.ConnectionAdapter; -//import ecologylab.net.PURLConnection; -//import ecologylab.net.ParsedURL; -//import ecologylab.serialization.ClassDescriptor; -//import ecologylab.serialization.DeserializationHookStrategy; -//import ecologylab.serialization.ElementState; -//import ecologylab.serialization.FieldDescriptor; -//import ecologylab.serialization.FieldTypes; -//import ecologylab.serialization.RootElementException; -//import ecologylab.serialization.SIMPLTranslationException; -//import ecologylab.serialization.ScalarUnmarshallingContext; -//import ecologylab.serialization.TranslationContext; -//import ecologylab.serialization.TranslationScope; -//import ecologylab.serialization.XMLReaderPool; -//import ecologylab.serialization.annotations.simpl_map_key_field; -//import ecologylab.serialization.types.element.IMappable; -// -///** -// * Use SAX to translate XML into a typed tree of ElementState objects. -// * -// * @author andruid -// */ -public class ElementStateSAXHandler // extends Debug implements ContentHandler, FieldTypes, ScalarUnmarshallingContext -{ -// -// final TranslationScope translationScope; -// -// ElementState root; -// -// // private XMLReader parser; -// -// /** -// * Current "DOM" frame state. -// */ -// ElementState currentElementState; -// -// /** -// * Optimizations for current field. -// */ -// FieldDescriptor currentFD; -// -// SIMPLTranslationException xmlTranslationException; -// -// ArrayList fdStack = new ArrayList(); -// -// static XMLReaderPool xmlReaderPool = new XMLReaderPool(1, 1); -// -// ParsedURL purlContext; -// -// File fileContext; -// -// DeserializationHookStrategy deserializationHookStrategy; -// -// TranslationContext translationContext = new TranslationContext(); -// -// private boolean skipClosingTag = false; -// -// /** -// * -// */ -// public ElementStateSAXHandler(TranslationScope translationScope, -// TranslationContext translationContext) -// { -// this.translationScope = translationScope; -// this.translationContext = translationContext; -// -// // try -// // { -// // parser = createXMLReader(); -// // parser.setContentHandler(this); -// // } catch (Exception e) -// // { -// // parser = null; -// // } -// } -// -// static final String SUN_XERCES_PARSER_NAME = "com.sun.org.apache.xerces.internal.parsers.SAXParser"; -// -// static Class parserClass; -// -// static boolean triedToFindParserClass; -// -// public static XMLReader createXMLReader() throws SAXException -// { -// if (parserClass != null) -// return ReflectionTools.getInstance(parserClass); -// // else -// -// if (!triedToFindParserClass) -// { -// triedToFindParserClass = true; -// try -// { -// parserClass = (Class) Class.forName(SUN_XERCES_PARSER_NAME); -// return createXMLReader(); -// } -// catch (Exception e) -// { -// -// } -// } -// // stuck doin it the slow way :-( -// return XMLReaderFactory.createXMLReader(); -// } -// -// /** -// * Parse the CharSequence of XML, using UTF-8 encoding. -// * -// * @param charSequence -// * @return -// * @throws SIMPLTranslationException -// */ -// public ElementState parse(CharSequence charSequence) throws SIMPLTranslationException -// { -// return parse(charSequence, StringInputStream.UTF8); -// } -// -// /** -// * Parse the CharSequence of XML, given the charsetType encoding info. -// * -// * @param charSequence -// * @param charsetType -// * @return -// * @throws SIMPLTranslationException -// */ -// public ElementState parse(CharSequence charSequence, int charsetType) -// throws SIMPLTranslationException -// { -// InputStream xmlStream = new StringInputStream(charSequence, charsetType); -// ElementState result = parse(xmlStream); -// try -// { -// xmlStream.close(); -// } -// catch (IOException e) -// { -// e.printStackTrace(); -// } -// return result; -// } -// -// public ElementState parseString(String xmlString) throws SIMPLTranslationException -// { -// StringReader reader = new StringReader(xmlString); -// ElementState result = parse(reader); -// reader.close(); -// -// return result; -// } -// -// static final ConnectionAdapter connectionAdapter = new ConnectionAdapter(); -// -// /** -// * Translate an XML document read from a URL to a strongly typed tree of XML objects. -// * -// * Use SAX or DOM parsing depending on the value of useDOMForTranslateTo. -// * -// * @param purl -// * XML source material. -// * @param translationScope -// * Specifies mapping from XML nodes (elements and attributes) to Java types. -// * -// * @return Strongly typed tree of ElementState objects. -// * @throws SIMPLTranslationException -// */ -// public ElementState parse(URL url) throws SIMPLTranslationException -// { -// return parse(new ParsedURL(url)); -// } -// -// /** -// * Translate an XML document read from a ParsedURL to a strongly typed tree of XML objects. -// * -// * Use SAX or DOM parsing depending on the value of useDOMForTranslateTo. -// * -// * @param purl -// * XML source material. -// * @param translationScope -// * Specifies mapping from XML nodes (elements and attributes) to Java types. -// * -// * @return Strongly typed tree of ElementState objects. -// * @throws SIMPLTranslationException -// */ -// public ElementState parse(ParsedURL purl) throws SIMPLTranslationException -// { -// if (purl.isFile()) -// return parse(purl.file()); -// -// this.purlContext = purl; -// -// PURLConnection purlConnection = purl.connect(connectionAdapter); -// ElementState result = parse(purlConnection.inputStream()); -// purlConnection.recycle(); -// this.purlContext = null; -// return result; -// } -// -// /** -// * Translate a file from XML to a strongly typed tree of XML objects. -// * -// * Use SAX or DOM parsing depending on the value of useDOMForTranslateTo. -// * -// * @param file -// * XML source material. -// * @param translationScope -// * Specifies mapping from XML nodes (elements and attributes) to Java types. -// * -// * @return Strongly typed tree of ElementState objects. -// * @throws SIMPLTranslationException -// */ -// -// public ElementState parse(File file) throws SIMPLTranslationException -// { -// try -// { -// FileInputStream fileInputStream = new FileInputStream(file); -// BufferedInputStream bufferedStream = new BufferedInputStream(fileInputStream); -// this.fileContext = file.getParentFile(); -// ElementState elementState = parse(bufferedStream); -// this.fileContext = null; -// bufferedStream.close(); -// return elementState; -// } -// catch (FileNotFoundException e) -// { -// this.fileContext = null; -// throw new SIMPLTranslationException("Can't open file " + file.getAbsolutePath(), e); -// } -// catch (IOException e) -// { -// this.fileContext = null; -// throw new SIMPLTranslationException("Can't close file " + file.getAbsolutePath(), e); -// } -// } -// -// public ElementState parse(Reader reader) throws SIMPLTranslationException -// { -// InputSource inputSource = new InputSource(reader); -// ElementState result = parse(inputSource); -// // TODO -- put this into a finally from the parse -// try -// { -// reader.close(); -// } -// catch (IOException e) -// { -// throw new SIMPLTranslationException("Can't close reader: " + reader, e); -// } -// return result; -// } -// -// public ElementState parse(InputStream inputStream, -// DeserializationHookStrategy deserializationHookStrategy) throws SIMPLTranslationException -// { -// this.deserializationHookStrategy = deserializationHookStrategy; -// return parse(new InputSource(inputStream)); -// } -// -// public ElementState parse(PURLConnection purlConnection, -// DeserializationHookStrategy deserializationHookStrategy) throws SIMPLTranslationException, -// IOException -// { -// this.deserializationHookStrategy = deserializationHookStrategy; -// this.purlContext = purlConnection.getPurl(); -// return parseAndThrowIO(new InputSource(purlConnection.inputStream())); -// } -// -// public ElementState parse(File file, DeserializationHookStrategy deserializationHookStrategy) -// throws SIMPLTranslationException -// { -// this.deserializationHookStrategy = deserializationHookStrategy; -// return parse(file); -// } -// -// public ElementState parse(ParsedURL purl, DeserializationHookStrategy deserializationHookStrategy) -// throws SIMPLTranslationException -// { -// this.deserializationHookStrategy = deserializationHookStrategy; -// return parse(purl); -// } -// -// public ElementState parse(CharSequence charSequence, -// DeserializationHookStrategy deserializationHookStrategy) throws SIMPLTranslationException -// { -// this.deserializationHookStrategy = deserializationHookStrategy; -// return parse(charSequence); -// } -// -// public ElementState parse(InputStream inputStream) throws SIMPLTranslationException -// { -// return parse(new InputSource(inputStream)); -// } -// -// public ElementState parse(InputSource inputSource) throws SIMPLTranslationException -// { -// ElementState result = null; -// try -// { -// result = parseAndThrowIO(inputSource); -// } -// catch (IOException e) -// { -// xmlTranslationException = new SIMPLTranslationException("IOException during parsing", e); -// } -// return result; -// } -// -// public ElementState parseAndThrowIO(InputSource inputSource) throws SIMPLTranslationException, -// IOException -// { -// XMLReader parser = null; -// try -// { -// parser = parseAndThrow(inputSource); -// } -// catch (SAXException e) -// { -// // (condition trys to ignore weird characters at the end of yahoo's xml on 9/9/08 -// if ((currentFD == null) || !(currentFD.getType() == PSEUDO_FIELD_DESCRIPTOR) -// && (currentElementState != null)) -// { -// xmlTranslationException = new SIMPLTranslationException("SAXException during parsing", e); -// -// // print xml -// if (root != null) -// { -// StringBuilder builder = root.serialize(); -// System.out.println("Failed XML:"); -// System.out.println(builder.toString()); -// } -// } -// } -// finally -// { -// if (parser != null) -// xmlReaderPool.release(parser); -// } -// if (xmlTranslationException != null) -// throw xmlTranslationException; -// return root; -// } -// -// /** -// * @param inputSource -// * @return -// * @throws IOException -// * @throws SAXException -// */ -// public XMLReader parseAndThrow(InputSource inputSource) throws IOException, SAXException -// { -// XMLReader parser; -// parser = xmlReaderPool.acquire(); -// parser.setContentHandler(this); -// parser.parse(inputSource); -// return parser; -// } -// -// private void setRoot(ElementState root) -// { -// this.root = root; -// this.currentElementState = root; -// } -// -// private ClassDescriptor currentClassDescriptor() -// { -// if (currentElementState != null) -// return this.currentElementState.classDescriptor(); -// else -// return null; -// } -// -// /** -// * -// * ${tags} -// * -// * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, -// * java.lang.String, org.xml.sax.Attributes) -// */ -// public void startElement(String uri, String localName, String tagName, Attributes attributes) -// throws SAXException -// { -// if (xmlTranslationException != null) -// return; -// -// FieldDescriptor childFD = null; -// final boolean isRoot = (root == null); -// if (isRoot) -// { // form the root ElementState! -// ClassDescriptor rootClassDescriptor = translationScope.getClassDescriptorByTag(tagName); -// if (rootClassDescriptor != null) -// { -// try -// { -// ElementState root = null; -// if (root == null) -// root = rootClassDescriptor.getInstance(); -// if (root != null) -// { -// root.setupRoot(); -// setRoot(root); -// root.deserializationPreHook(); -// if (deserializationHookStrategy != null) -// deserializationHookStrategy.deserializationPreHook(root, null); -// root.translateAttributes(translationScope, attributes, this, root, translationContext); -// childFD = rootClassDescriptor.pseudoFieldDescriptor(); -// } -// else -// { -// this.xmlTranslationException = new RootElementException(tagName, translationScope); -// return; -// } -// } -// catch (SIMPLTranslationException e) -// { -// xmlTranslationException = e; -// } -// } -// else -// { -// // else, we dont translate this element; we ignore it. -// String message = "XML Translation WARNING: Cant find class object for Root XML element <" -// + tagName + ">: Ignored. "; -// println(message); -// xmlTranslationException = new SIMPLTranslationException(message); -// return; -// } -// } -// else -// // not root -// { -// final int currentType = currentFD.getType(); -// ElementState currentES = this.currentElementState; -// // if there is a pending text node, assign it somehow! -// processPendingScalar(currentType, currentES); -// -// ClassDescriptor currentClassDescriptor = currentClassDescriptor(); -// childFD = (currentFD != null) && (currentType == IGNORED_ELEMENT) ? -// // new NodeToJavaOptimizations(tagName) : // (nice for debugging; slows us down) -// FieldDescriptor.IGNORED_ELEMENT_FIELD_DESCRIPTOR -// : (currentType == WRAPPER) ? currentFD.getWrappedFD() : currentClassDescriptor -// .getFieldDescriptorByTag(tagName, translationScope, currentES); -// if (childFD == null) -// { -// childFD = makeIgnoredFieldDescriptor(tagName, currentClassDescriptor); -// } -// } -// this.currentFD = childFD; -// registerXMLNS(); -// // TODO? -- do we need to avoid this if null from an exception in translating root? -// pushFD(childFD); -// // printStack("After push"); -// -// if (isRoot) -// return; -// -// ElementState currentElementState = this.currentElementState; -// ElementState childES = null; -// try -// { -// switch (childFD.getType()) -// { -// case COMPOSITE_ELEMENT: -// childES = childFD.constructChildElementState(currentElementState, tagName, attributes, -// translationContext); -// -// if (childES == currentElementState) -// skipClosingTag = true; -// -// if (childES == null) -// { -// childFD = makeIgnoredFieldDescriptor(tagName, currentClassDescriptor()); -// } -// else -// childFD.setFieldToComposite(currentElementState, childES); // maybe we -// // should do -// // this on close -// // element -// break; -// case NAME_SPACE_NESTED_ELEMENT: -// // TODO Name Space support! -// // ElementState nsContext = -// // currentElementState.getNestedNameSpace(activeFieldDescriptor.nameSpaceID()); -// // childES = activeFieldDescriptor.constructChildElementState(nsContext); -// // activeFieldDescriptor.setFieldToNestedObject(nsContext, childES); -// break; -// case NAME_SPACE_SCALAR: -// // TODO Name Space support! -// // childES = currentElementState.getNestedNameSpace(activeFieldDescriptor.nameSpaceID()); -// break; -// case SCALAR: -// // wait for characters to set scalar field -// // activeN2JO.setScalarFieldWithLeafNode(activeES, childNode); -// break; -// case COLLECTION_ELEMENT: -// Collection collection = (Collection) childFD -// .automaticLazyGetCollectionOrMap(currentElementState); -// if (collection != null) -// { -// ElementState childElement = childFD.constructChildElementState(currentElementState, -// tagName, attributes, translationContext); -// childES = childElement; -// -// if (childES == null) -// { -// childFD = makeIgnoredFieldDescriptor(tagName, currentClassDescriptor()); -// } -// -// collection.add(childES); -// } -// // activeNJO.formElementAndAddToCollection(activeES, childNode); -// break; -// case COLLECTION_SCALAR: -// // wait for characters to create scalar reference type and add to collection -// // activeN2JO.addLeafNodeToCollection(activeES, childNode); -// break; -// case MAP_ELEMENT: -// Map map = (Map) childFD.automaticLazyGetCollectionOrMap(currentElementState); -// if (map != null) -// { -// ElementState childElement = childFD.constructChildElementState(currentElementState, -// tagName, attributes, translationContext); -// -// childES = childElement; -// if (childES == null) -// { -// this.currentFD = makeIgnoredFieldDescriptor(tagName, currentClassDescriptor()); -// } -// } -// // Map map = activeFieldDescriptor.getMap(currentElementState); -// // if (map != null) -// // { -// // childES = activeFieldDescriptor.constructChildElementState(currentElementState, tagName); -// // } -// break; -// case IGNORED_ELEMENT: -// // should get a set of Optimizations for this, to represent its subfields -// case BAD_FIELD: -// case WRAPPER: -// default: -// break; -// -// } -// if (childES != null) -// { -// // fill in its attributes -// if (deserializationHookStrategy != null) -// deserializationHookStrategy.deserializationPreHook(childES, childFD); -// -// childES.translateAttributes(translationScope, attributes, this, currentElementState, -// translationContext); -// childES.deserializationPreHook(); -// -// this.currentElementState = childES; // childES.parent = old currentElementState -// this.currentFD = childFD; -// } -// } -// catch (SIMPLTranslationException e) -// { -// this.xmlTranslationException = e; -// } -// } -// -// private FieldDescriptor makeIgnoredFieldDescriptor(String tagName, -// ClassDescriptor currentClassDescriptor) -// { -// FieldDescriptor activeFieldDescriptor; -// currentClassDescriptor.warning(" Ignoring tag <" + tagName + ">"); -// activeFieldDescriptor = new FieldDescriptor(tagName); // TODO -- should we record -// // declaringClass in here??! -// if (activeFieldDescriptor.getTagName() != null) -// currentClassDescriptor.addFieldDescriptorMapping(activeFieldDescriptor); -// return activeFieldDescriptor; -// } -// -// private void pushFD(FieldDescriptor fd) -// { -// this.fdStack.add(fd); -// } -// -// private void popAndPeekFD() -// { -// ArrayList stack = this.fdStack; -// int last = stack.size() - 1; -// if (last >= 0) -// { -// FieldDescriptor result = stack.remove(last--); -// if (last >= 0) -// result = stack.get(last); -// this.currentFD = result; -// // printStack("After Pop"); -// } -// } -// -// /** -// * -// * ${tags} -// * -// * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, -// * java.lang.String) -// */ -// public void endElement(String namespaceURI, String localTagName, String prefixedTagName) -// throws SAXException -// { -// if (skipClosingTag) -// { -// skipClosingTag = false; -// return; -// } -// -// // if (this.currentElementState == null) -// // { -// // this.currentFD.warning(" Ignoring tag <" + localTagName + ">"); -// // return; -// // } -// -// if (xmlTranslationException != null) -// return; -// -// final FieldDescriptor currentFD = this.currentFD; -// final int curentFdType = currentFD.getType(); -// -// if (curentFdType == NAMESPACE_TRIAL_ELEMENT) -// { -// // re-attempt lookup in case we figured out how -// -// // if not, we will have to set currentFdType = NAMESPACE_IGNORED_ELEMENT -// } -// -// ElementState currentES = this.currentElementState; -// processPendingScalar(curentFdType, currentES); -// -// final ElementState parentES; -// -// if (currentES.parents == null || currentES.parents.isEmpty()) -// parentES = currentES.parent; -// else -// parentES = currentES.parents.peek(); -// -// // final ElementState parentES = currentES.parent; -// -// switch (curentFdType) -// // every good push deserves a pop :-) (and othertimes, not!) -// { -// case MAP_ELEMENT: -// if (currentES instanceof IMappable) -// { -// final Object key = ((IMappable) currentES).key(); -// Map map = (Map) currentFD.automaticLazyGetCollectionOrMap(parentES); -// // Map map = currentFD.getMap(parentES); -// map.put(key, currentES); -// } -// else -// { -// String mapKeyFieldName = currentFD.getMapKeyFieldName(); -// FieldDescriptor elementMapKeyFD = null; -// if (mapKeyFieldName != null) -// { -// ClassDescriptor currentMapElementCD = currentFD.getElementClassDescriptor(); -// elementMapKeyFD = currentMapElementCD.getFieldDescriptorByFieldName(mapKeyFieldName); -// if (elementMapKeyFD != null) -// { -// try -// { -// Object key = elementMapKeyFD.getField().get(currentES); -// Map map = (Map) currentFD.automaticLazyGetCollectionOrMap(parentES); -// map.put(key, currentES); -// } -// catch (IllegalArgumentException e) -// { -// this.xmlTranslationException = new SIMPLTranslationException("field not found: " + elementMapKeyFD.getField() + " on " + currentES, e); -// } -// catch (IllegalAccessException e) -// { -// this.xmlTranslationException = new SIMPLTranslationException("cannot access field: " + elementMapKeyFD.getField() + " on " + currentES, e); -// } -// } -// } -// if (mapKeyFieldName == null || elementMapKeyFD == null) -// this.xmlTranslationException = new SIMPLTranslationException("a map element should either implement Mappable or have annotation " + simpl_map_key_field.class.getSimpleName()); -// } -// case COMPOSITE_ELEMENT: -// case COLLECTION_ELEMENT: -// case NAME_SPACE_NESTED_ELEMENT: -// if (parentES != null) -// parentES.createChildHook(currentES); -// else -// debug("cool - post ns element"); -// currentES.deserializationPostHook(); -// if (deserializationHookStrategy != null) -// deserializationHookStrategy.deserializationPostHook(currentES, currentFD); -// this.currentElementState = parentES; -// case NAME_SPACE_SCALAR: -// // case WRAPPER: -// this.currentElementState = parentES; // restore context! -// break; -// default: -// break; -// } -// // end of the Namespace object, so we gotta pop it off, too. -// // if (curentN2JOType == NAME_SPACE_NESTED_ELEMENT) -// // this.currentElementState = this.currentElementState.parent; -// popAndPeekFD(); -// -// if (currentES.parents != null && !currentES.parents.isEmpty() && currentES.parents.size() > 1) -// currentES.parents.pop(); -// // if (this.startElementPushed) // every good push deserves a pop :-) (and othertimes, not!) -// } -// -// /** -// * Assign pending value to a @simpl_scalar -// * -// * @param curentN2JOType -// * @param currentES -// */ -// private void processPendingScalar(final int curentN2JOType, ElementState currentES) -// { -// final int length = currentTextValue.length(); -// if (length > 0) -// { -// try -// { -// switch (curentN2JOType) -// { -// case NAME_SPACE_SCALAR: -// case SCALAR: -// // TODO -- unmarshall to set field with scalar type -// // copy from the StringBuilder -// String value = stringToDeserializeAsScalar(length); -// currentFD.setFieldToScalar(currentES, value, this); -// break; -// case COLLECTION_SCALAR: -// value = stringToDeserializeAsScalar(length); -// currentFD.addLeafNodeToCollection(currentES, value, this); -// break; -// case COMPOSITE_ELEMENT: -// case COLLECTION_ELEMENT: -// case PSEUDO_FIELD_DESCRIPTOR: -// // TODO - is this code used???? -// // optimizations in currentN2JO are for its parent (they were in scope when it was -// // constructed) -// // so we get the optimizations we need from the currentElementState -// // FIXME -- implement this!!! -// FieldDescriptor scalarTextFD = currentElementState.classDescriptor().getScalarTextFD(); -// if (scalarTextFD != null) -// { -// value = stringToDeserializeAsScalar(length); -// scalarTextFD.setFieldToScalar(currentES, value, this); -// } -// break; -// default: -// break; -// } -// } -// catch (SIMPLTranslationException e) -// { -// this.xmlTranslationException = e; -// } -// -// currentTextValue.setLength(0); -// } -// } -// -// /** -// * Get the String that will be marshalled into the value with a ScalarType, using the -// * currentTextValue state variable from the parse, and the length parameter. If appropriate, use -// * the currentFD to perform a regex filter on the value before passing it to the appropriate -// * scalar marshalling and field or collection element setter. -// * -// * @param length -// * @return -// */ -// private String stringToDeserializeAsScalar(final int length) -// { -// String result = new String(currentTextValue.substring(0, length)); -// if (translationScope.isPerformFilters()) -// result = currentFD.filterValue(result); -// return result; -// } -// -// void printStack(String msg) -// { -// currentElementState.debug("Stack -- " + msg + "\t[" + this.currentElementState + "]"); -// for (FieldDescriptor thatFD : fdStack) -// { -// println(thatFD.getTagName() + " - 0x" + Integer.toHexString(thatFD.getType())); -// } -// println(""); -// } -// -// StringBuilder currentTextValue = new StringBuilder(1024); -// -// /** -// * -// * ${tags} -// * -// * @see org.xml.sax.ContentHandler#characters(char[], int, int) -// */ -// public void characters(char[] chars, int startIndex, int length) throws SAXException -// { -// if (xmlTranslationException != null) -// return; -// -// if (currentFD != null) -// { -// int n2joType = currentFD.getType(); -// switch (n2joType) -// { -// case SCALAR: -// case COLLECTION_SCALAR: -// currentTextValue.append(chars, startIndex, length); -// // TODO -- unmarshall to set field with scalar type -// break; -// case COMPOSITE_ELEMENT: -// case COLLECTION_ELEMENT: -// case PSEUDO_FIELD_DESCRIPTOR: -// // optimizations in currentN2JO are for its parent (they were in scope when it was -// // constructed) -// // so we get the optimizations we need from the currentElementState -// if (currentElementState.classDescriptor().hasScalarFD()) -// currentTextValue.append(chars, startIndex, length); -// break; -// default: -// // TODO ?! can we dump characters in this case, or should we append to textNode?! -// // currentElementState.appendLeafXML(buffy, leafElementName, leafValue, needsEscaping, -// // isCDATA) -// break; -// } -// } -// } -// -// /** -// * -// * ${tags} -// * -// * @see org.xml.sax.ContentHandler#endDocument() -// */ -// public void endDocument() throws SAXException -// { -// if ((xmlTranslationException == null) && (root != null)) -// root.deserializationPostHook(); -// } -// -// /** -// * -// * ${tags} -// * -// * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String) -// */ -// public void endPrefixMapping(String prefix) throws SAXException -// { -// // TODO Auto-generated method stub -// -// } -// -// /** -// * -// * ${tags} -// * -// * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int) -// */ -// public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException -// { -// // TODO Auto-generated method stub -// -// } -// -// /** -// * -// * ${tags} -// * -// * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String) -// */ -// public void processingInstruction(String target, String data) throws SAXException -// { -// // TODO Auto-generated method stub -// -// } -// -// /** -// * -// * ${tags} -// * -// * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator) -// */ -// public void setDocumentLocator(Locator locator) -// { -// // TODO Auto-generated method stub -// -// } -// -// /** -// * -// * ${tags} -// * -// * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String) -// */ -// public void skippedEntity(String name) throws SAXException -// { -// // TODO Auto-generated method stub -// -// } -// -// /** -// * -// * ${tags} -// * -// * @see org.xml.sax.ContentHandler#startDocument() -// */ -// public void startDocument() throws SAXException -// { -// // TODO Auto-generated method stub -// -// } -// -// /** -// * -// * ${tags} -// * -// * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) -// */ -// public void startPrefixMapping(String nsID, String urn) throws SAXException -// { -// // debug("Hi: startPrefixMapping(" + nsID +" := " + urn); -// // this.nameSpacePrefix = prefix; -// // this.nameSpaceURN = urn; -// if (nsID.length() > 0) // these days, ignore ns decls without an id (default ones) -// { -// // push the urn in first; pop it off 2nd -// xmlnsStack.add(urn); -// // push the nsID in 2nd; pop it off 1st -// xmlnsStack.add(nsID); -// } -// } -// -// // String nameSpacePrefix; -// // -// // String nameSpaceURN; //FIXME -- this should be a stack! -// -// ArrayList xmlnsStack = new ArrayList(2); -// -// void registerXMLNS() -// { -// int size = xmlnsStack.size(); -// while (size >= 2) -// { -// String nameSpaceID = xmlnsStack.remove(--size); -// String urn = xmlnsStack.remove(--size); -// if ((nameSpaceID != null) && (urn != null)) -// { -// registerXMLNS(this.currentElementState, nameSpaceID, urn); -// } -// } -// // String urn = nameSpaceURN; -// // if (urn != null) -// // { -// // registerXMLNS(this.currentElementState, nameSpacePrefix, urn); -// // nameSpaceURN = null; -// // nameSpacePrefix = null; -// // } -// } -// -// /** -// * Create a name space object, nested in the context, using info saved in this. -// * -// * @param context -// * @param urn -// * The value of the xmlns:id attribute is the URL that is mapped to the class. -// */ -// private void registerXMLNS(ElementState context, String prefix, String urn) -// { -// if (context != null) -// context.classDescriptor().mapNamespaceIdToClass(translationScope, prefix, urn); -// else -// println("ERROR: Null context. Can't register xmlns:" + prefix + "=" + urn); -// } -// -// /** -// * @return the root -// */ -// public ElementState root() -// { -// return root; -// } -// -// public File fileContext() -// { -// return (fileContext != null) ? fileContext : (purlContext != null) ? purlContext.file() : null; -// } -// -// public ParsedURL purlContext() -// { -// return (purlContext != null) ? purlContext : (fileContext != null) ? new ParsedURL(fileContext) -// : null; -// } -// -} +///** +// * +// */ +package ecologylab.serialization.deserializers.pushhandlers; +// +//import java.io.BufferedInputStream; +//import java.io.File; +//import java.io.FileInputStream; +//import java.io.FileNotFoundException; +//import java.io.IOException; +//import java.io.InputStream; +//import java.io.Reader; +//import java.io.StringReader; +//import java.net.URL; +//import java.util.ArrayList; +//import java.util.Collection; +//import java.util.Map; +// +//import org.xml.sax.Attributes; +//import org.xml.sax.ContentHandler; +//import org.xml.sax.InputSource; +//import org.xml.sax.Locator; +//import org.xml.sax.SAXException; +//import org.xml.sax.XMLReader; +//import org.xml.sax.helpers.XMLReaderFactory; +// +//import ecologylab.generic.Debug; +//import ecologylab.generic.ReflectionTools; +//import ecologylab.generic.StringInputStream; +//import ecologylab.net.ConnectionAdapter; +//import ecologylab.net.PURLConnection; +//import ecologylab.net.ParsedURL; +//import ecologylab.serialization.ClassDescriptor; +//import ecologylab.serialization.DeserializationHookStrategy; +//import ecologylab.serialization.ElementState; +//import ecologylab.serialization.FieldDescriptor; +//import ecologylab.serialization.FieldTypes; +//import ecologylab.serialization.RootElementException; +//import ecologylab.serialization.SIMPLTranslationException; +//import ecologylab.serialization.ScalarUnmarshallingContext; +//import ecologylab.serialization.TranslationContext; +//import ecologylab.serialization.TranslationScope; +//import ecologylab.serialization.XMLReaderPool; +//import ecologylab.serialization.annotations.simpl_map_key_field; +//import ecologylab.serialization.types.element.IMappable; +// +///** +// * Use SAX to translate XML into a typed tree of ElementState objects. +// * +// * @author andruid +// */ +public class ElementStateSAXHandler // extends Debug implements ContentHandler, FieldTypes, ScalarUnmarshallingContext +{ +// +// final TranslationScope translationScope; +// +// ElementState root; +// +// // private XMLReader parser; +// +// /** +// * Current "DOM" frame state. +// */ +// ElementState currentElementState; +// +// /** +// * Optimizations for current field. +// */ +// FieldDescriptor currentFD; +// +// SIMPLTranslationException xmlTranslationException; +// +// ArrayList fdStack = new ArrayList(); +// +// static XMLReaderPool xmlReaderPool = new XMLReaderPool(1, 1); +// +// ParsedURL purlContext; +// +// File fileContext; +// +// DeserializationHookStrategy deserializationHookStrategy; +// +// TranslationContext translationContext = new TranslationContext(); +// +// private boolean skipClosingTag = false; +// +// /** +// * +// */ +// public ElementStateSAXHandler(TranslationScope translationScope, +// TranslationContext translationContext) +// { +// this.translationScope = translationScope; +// this.translationContext = translationContext; +// +// // try +// // { +// // parser = createXMLReader(); +// // parser.setContentHandler(this); +// // } catch (Exception e) +// // { +// // parser = null; +// // } +// } +// +// static final String SUN_XERCES_PARSER_NAME = "com.sun.org.apache.xerces.internal.parsers.SAXParser"; +// +// static Class parserClass; +// +// static boolean triedToFindParserClass; +// +// public static XMLReader createXMLReader() throws SAXException +// { +// if (parserClass != null) +// return ReflectionTools.getInstance(parserClass); +// // else +// +// if (!triedToFindParserClass) +// { +// triedToFindParserClass = true; +// try +// { +// parserClass = (Class) Class.forName(SUN_XERCES_PARSER_NAME); +// return createXMLReader(); +// } +// catch (Exception e) +// { +// +// } +// } +// // stuck doin it the slow way :-( +// return XMLReaderFactory.createXMLReader(); +// } +// +// /** +// * Parse the CharSequence of XML, using UTF-8 encoding. +// * +// * @param charSequence +// * @return +// * @throws SIMPLTranslationException +// */ +// public ElementState parse(CharSequence charSequence) throws SIMPLTranslationException +// { +// return parse(charSequence, StringInputStream.UTF8); +// } +// +// /** +// * Parse the CharSequence of XML, given the charsetType encoding info. +// * +// * @param charSequence +// * @param charsetType +// * @return +// * @throws SIMPLTranslationException +// */ +// public ElementState parse(CharSequence charSequence, int charsetType) +// throws SIMPLTranslationException +// { +// InputStream xmlStream = new StringInputStream(charSequence, charsetType); +// ElementState result = parse(xmlStream); +// try +// { +// xmlStream.close(); +// } +// catch (IOException e) +// { +// e.printStackTrace(); +// } +// return result; +// } +// +// public ElementState parseString(String xmlString) throws SIMPLTranslationException +// { +// StringReader reader = new StringReader(xmlString); +// ElementState result = parse(reader); +// reader.close(); +// +// return result; +// } +// +// static final ConnectionAdapter connectionAdapter = new ConnectionAdapter(); +// +// /** +// * Translate an XML document read from a URL to a strongly typed tree of XML objects. +// * +// * Use SAX or DOM parsing depending on the value of useDOMForTranslateTo. +// * +// * @param purl +// * XML source material. +// * @param translationScope +// * Specifies mapping from XML nodes (elements and attributes) to Java types. +// * +// * @return Strongly typed tree of ElementState objects. +// * @throws SIMPLTranslationException +// */ +// public ElementState parse(URL url) throws SIMPLTranslationException +// { +// return parse(new ParsedURL(url)); +// } +// +// /** +// * Translate an XML document read from a ParsedURL to a strongly typed tree of XML objects. +// * +// * Use SAX or DOM parsing depending on the value of useDOMForTranslateTo. +// * +// * @param purl +// * XML source material. +// * @param translationScope +// * Specifies mapping from XML nodes (elements and attributes) to Java types. +// * +// * @return Strongly typed tree of ElementState objects. +// * @throws SIMPLTranslationException +// */ +// public ElementState parse(ParsedURL purl) throws SIMPLTranslationException +// { +// if (purl.isFile()) +// return parse(purl.file()); +// +// this.purlContext = purl; +// +// PURLConnection purlConnection = purl.connect(connectionAdapter); +// ElementState result = parse(purlConnection.inputStream()); +// purlConnection.recycle(); +// this.purlContext = null; +// return result; +// } +// +// /** +// * Translate a file from XML to a strongly typed tree of XML objects. +// * +// * Use SAX or DOM parsing depending on the value of useDOMForTranslateTo. +// * +// * @param file +// * XML source material. +// * @param translationScope +// * Specifies mapping from XML nodes (elements and attributes) to Java types. +// * +// * @return Strongly typed tree of ElementState objects. +// * @throws SIMPLTranslationException +// */ +// +// public ElementState parse(File file) throws SIMPLTranslationException +// { +// try +// { +// FileInputStream fileInputStream = new FileInputStream(file); +// BufferedInputStream bufferedStream = new BufferedInputStream(fileInputStream); +// this.fileContext = file.getParentFile(); +// ElementState elementState = parse(bufferedStream); +// this.fileContext = null; +// bufferedStream.close(); +// return elementState; +// } +// catch (FileNotFoundException e) +// { +// this.fileContext = null; +// throw new SIMPLTranslationException("Can't open file " + file.getAbsolutePath(), e); +// } +// catch (IOException e) +// { +// this.fileContext = null; +// throw new SIMPLTranslationException("Can't close file " + file.getAbsolutePath(), e); +// } +// } +// +// public ElementState parse(Reader reader) throws SIMPLTranslationException +// { +// InputSource inputSource = new InputSource(reader); +// ElementState result = parse(inputSource); +// // TODO -- put this into a finally from the parse +// try +// { +// reader.close(); +// } +// catch (IOException e) +// { +// throw new SIMPLTranslationException("Can't close reader: " + reader, e); +// } +// return result; +// } +// +// public ElementState parse(InputStream inputStream, +// DeserializationHookStrategy deserializationHookStrategy) throws SIMPLTranslationException +// { +// this.deserializationHookStrategy = deserializationHookStrategy; +// return parse(new InputSource(inputStream)); +// } +// +// public ElementState parse(PURLConnection purlConnection, +// DeserializationHookStrategy deserializationHookStrategy) throws SIMPLTranslationException, +// IOException +// { +// this.deserializationHookStrategy = deserializationHookStrategy; +// this.purlContext = purlConnection.getPurl(); +// return parseAndThrowIO(new InputSource(purlConnection.inputStream())); +// } +// +// public ElementState parse(File file, DeserializationHookStrategy deserializationHookStrategy) +// throws SIMPLTranslationException +// { +// this.deserializationHookStrategy = deserializationHookStrategy; +// return parse(file); +// } +// +// public ElementState parse(ParsedURL purl, DeserializationHookStrategy deserializationHookStrategy) +// throws SIMPLTranslationException +// { +// this.deserializationHookStrategy = deserializationHookStrategy; +// return parse(purl); +// } +// +// public ElementState parse(CharSequence charSequence, +// DeserializationHookStrategy deserializationHookStrategy) throws SIMPLTranslationException +// { +// this.deserializationHookStrategy = deserializationHookStrategy; +// return parse(charSequence); +// } +// +// public ElementState parse(InputStream inputStream) throws SIMPLTranslationException +// { +// return parse(new InputSource(inputStream)); +// } +// +// public ElementState parse(InputSource inputSource) throws SIMPLTranslationException +// { +// ElementState result = null; +// try +// { +// result = parseAndThrowIO(inputSource); +// } +// catch (IOException e) +// { +// xmlTranslationException = new SIMPLTranslationException("IOException during parsing", e); +// } +// return result; +// } +// +// public ElementState parseAndThrowIO(InputSource inputSource) throws SIMPLTranslationException, +// IOException +// { +// XMLReader parser = null; +// try +// { +// parser = parseAndThrow(inputSource); +// } +// catch (SAXException e) +// { +// // (condition trys to ignore weird characters at the end of yahoo's xml on 9/9/08 +// if ((currentFD == null) || !(currentFD.getType() == PSEUDO_FIELD_DESCRIPTOR) +// && (currentElementState != null)) +// { +// xmlTranslationException = new SIMPLTranslationException("SAXException during parsing", e); +// +// // print xml +// if (root != null) +// { +// StringBuilder builder = root.serialize(); +// System.out.println("Failed XML:"); +// System.out.println(builder.toString()); +// } +// } +// } +// finally +// { +// if (parser != null) +// xmlReaderPool.release(parser); +// } +// if (xmlTranslationException != null) +// throw xmlTranslationException; +// return root; +// } +// +// /** +// * @param inputSource +// * @return +// * @throws IOException +// * @throws SAXException +// */ +// public XMLReader parseAndThrow(InputSource inputSource) throws IOException, SAXException +// { +// XMLReader parser; +// parser = xmlReaderPool.acquire(); +// parser.setContentHandler(this); +// parser.parse(inputSource); +// return parser; +// } +// +// private void setRoot(ElementState root) +// { +// this.root = root; +// this.currentElementState = root; +// } +// +// private ClassDescriptor currentClassDescriptor() +// { +// if (currentElementState != null) +// return this.currentElementState.classDescriptor(); +// else +// return null; +// } +// +// /** +// * +// * ${tags} +// * +// * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, +// * java.lang.String, org.xml.sax.Attributes) +// */ +// public void startElement(String uri, String localName, String tagName, Attributes attributes) +// throws SAXException +// { +// if (xmlTranslationException != null) +// return; +// +// FieldDescriptor childFD = null; +// final boolean isRoot = (root == null); +// if (isRoot) +// { // form the root ElementState! +// ClassDescriptor rootClassDescriptor = translationScope.getClassDescriptorByTag(tagName); +// if (rootClassDescriptor != null) +// { +// try +// { +// ElementState root = null; +// if (root == null) +// root = rootClassDescriptor.getInstance(); +// if (root != null) +// { +// root.setupRoot(); +// setRoot(root); +// root.deserializationPreHook(); +// if (deserializationHookStrategy != null) +// deserializationHookStrategy.deserializationPreHook(root, null); +// root.translateAttributes(translationScope, attributes, this, root, translationContext); +// childFD = rootClassDescriptor.pseudoFieldDescriptor(); +// } +// else +// { +// this.xmlTranslationException = new RootElementException(tagName, translationScope); +// return; +// } +// } +// catch (SIMPLTranslationException e) +// { +// xmlTranslationException = e; +// } +// } +// else +// { +// // else, we dont translate this element; we ignore it. +// String message = "XML Translation WARNING: Cant find class object for Root XML element <" +// + tagName + ">: Ignored. "; +// println(message); +// xmlTranslationException = new SIMPLTranslationException(message); +// return; +// } +// } +// else +// // not root +// { +// final int currentType = currentFD.getType(); +// ElementState currentES = this.currentElementState; +// // if there is a pending text node, assign it somehow! +// processPendingScalar(currentType, currentES); +// +// ClassDescriptor currentClassDescriptor = currentClassDescriptor(); +// childFD = (currentFD != null) && (currentType == IGNORED_ELEMENT) ? +// // new NodeToJavaOptimizations(tagName) : // (nice for debugging; slows us down) +// FieldDescriptor.IGNORED_ELEMENT_FIELD_DESCRIPTOR +// : (currentType == WRAPPER) ? currentFD.getWrappedFD() : currentClassDescriptor +// .getFieldDescriptorByTag(tagName, translationScope, currentES); +// if (childFD == null) +// { +// childFD = makeIgnoredFieldDescriptor(tagName, currentClassDescriptor); +// } +// } +// this.currentFD = childFD; +// registerXMLNS(); +// // TODO? -- do we need to avoid this if null from an exception in translating root? +// pushFD(childFD); +// // printStack("After push"); +// +// if (isRoot) +// return; +// +// ElementState currentElementState = this.currentElementState; +// ElementState childES = null; +// try +// { +// switch (childFD.getType()) +// { +// case COMPOSITE_ELEMENT: +// childES = childFD.constructChildElementState(currentElementState, tagName, attributes, +// translationContext); +// +// if (childES == currentElementState) +// skipClosingTag = true; +// +// if (childES == null) +// { +// childFD = makeIgnoredFieldDescriptor(tagName, currentClassDescriptor()); +// } +// else +// childFD.setFieldToComposite(currentElementState, childES); // maybe we +// // should do +// // this on close +// // element +// break; +// case NAME_SPACE_NESTED_ELEMENT: +// // TODO Name Space support! +// // ElementState nsContext = +// // currentElementState.getNestedNameSpace(activeFieldDescriptor.nameSpaceID()); +// // childES = activeFieldDescriptor.constructChildElementState(nsContext); +// // activeFieldDescriptor.setFieldToNestedObject(nsContext, childES); +// break; +// case NAME_SPACE_SCALAR: +// // TODO Name Space support! +// // childES = currentElementState.getNestedNameSpace(activeFieldDescriptor.nameSpaceID()); +// break; +// case SCALAR: +// // wait for characters to set scalar field +// // activeN2JO.setScalarFieldWithLeafNode(activeES, childNode); +// break; +// case COLLECTION_ELEMENT: +// Collection collection = (Collection) childFD +// .automaticLazyGetCollectionOrMap(currentElementState); +// if (collection != null) +// { +// ElementState childElement = childFD.constructChildElementState(currentElementState, +// tagName, attributes, translationContext); +// childES = childElement; +// +// if (childES == null) +// { +// childFD = makeIgnoredFieldDescriptor(tagName, currentClassDescriptor()); +// } +// +// collection.add(childES); +// } +// // activeNJO.formElementAndAddToCollection(activeES, childNode); +// break; +// case COLLECTION_SCALAR: +// // wait for characters to create scalar reference type and add to collection +// // activeN2JO.addLeafNodeToCollection(activeES, childNode); +// break; +// case MAP_ELEMENT: +// Map map = (Map) childFD.automaticLazyGetCollectionOrMap(currentElementState); +// if (map != null) +// { +// ElementState childElement = childFD.constructChildElementState(currentElementState, +// tagName, attributes, translationContext); +// +// childES = childElement; +// if (childES == null) +// { +// this.currentFD = makeIgnoredFieldDescriptor(tagName, currentClassDescriptor()); +// } +// } +// // Map map = activeFieldDescriptor.getMap(currentElementState); +// // if (map != null) +// // { +// // childES = activeFieldDescriptor.constructChildElementState(currentElementState, tagName); +// // } +// break; +// case IGNORED_ELEMENT: +// // should get a set of Optimizations for this, to represent its subfields +// case BAD_FIELD: +// case WRAPPER: +// default: +// break; +// +// } +// if (childES != null) +// { +// // fill in its attributes +// if (deserializationHookStrategy != null) +// deserializationHookStrategy.deserializationPreHook(childES, childFD); +// +// childES.translateAttributes(translationScope, attributes, this, currentElementState, +// translationContext); +// childES.deserializationPreHook(); +// +// this.currentElementState = childES; // childES.parent = old currentElementState +// this.currentFD = childFD; +// } +// } +// catch (SIMPLTranslationException e) +// { +// this.xmlTranslationException = e; +// } +// } +// +// private FieldDescriptor makeIgnoredFieldDescriptor(String tagName, +// ClassDescriptor currentClassDescriptor) +// { +// FieldDescriptor activeFieldDescriptor; +// currentClassDescriptor.warning(" Ignoring tag <" + tagName + ">"); +// activeFieldDescriptor = new FieldDescriptor(tagName); // TODO -- should we record +// // declaringClass in here??! +// if (activeFieldDescriptor.getTagName() != null) +// currentClassDescriptor.addFieldDescriptorMapping(activeFieldDescriptor); +// return activeFieldDescriptor; +// } +// +// private void pushFD(FieldDescriptor fd) +// { +// this.fdStack.add(fd); +// } +// +// private void popAndPeekFD() +// { +// ArrayList stack = this.fdStack; +// int last = stack.size() - 1; +// if (last >= 0) +// { +// FieldDescriptor result = stack.remove(last--); +// if (last >= 0) +// result = stack.get(last); +// this.currentFD = result; +// // printStack("After Pop"); +// } +// } +// +// /** +// * +// * ${tags} +// * +// * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, +// * java.lang.String) +// */ +// public void endElement(String namespaceURI, String localTagName, String prefixedTagName) +// throws SAXException +// { +// if (skipClosingTag) +// { +// skipClosingTag = false; +// return; +// } +// +// // if (this.currentElementState == null) +// // { +// // this.currentFD.warning(" Ignoring tag <" + localTagName + ">"); +// // return; +// // } +// +// if (xmlTranslationException != null) +// return; +// +// final FieldDescriptor currentFD = this.currentFD; +// final int curentFdType = currentFD.getType(); +// +// if (curentFdType == NAMESPACE_TRIAL_ELEMENT) +// { +// // re-attempt lookup in case we figured out how +// +// // if not, we will have to set currentFdType = NAMESPACE_IGNORED_ELEMENT +// } +// +// ElementState currentES = this.currentElementState; +// processPendingScalar(curentFdType, currentES); +// +// final ElementState parentES; +// +// if (currentES.parents == null || currentES.parents.isEmpty()) +// parentES = currentES.parent; +// else +// parentES = currentES.parents.peek(); +// +// // final ElementState parentES = currentES.parent; +// +// switch (curentFdType) +// // every good push deserves a pop :-) (and othertimes, not!) +// { +// case MAP_ELEMENT: +// if (currentES instanceof IMappable) +// { +// final Object key = ((IMappable) currentES).key(); +// Map map = (Map) currentFD.automaticLazyGetCollectionOrMap(parentES); +// // Map map = currentFD.getMap(parentES); +// map.put(key, currentES); +// } +// else +// { +// String mapKeyFieldName = currentFD.getMapKeyFieldName(); +// FieldDescriptor elementMapKeyFD = null; +// if (mapKeyFieldName != null) +// { +// ClassDescriptor currentMapElementCD = currentFD.getElementClassDescriptor(); +// elementMapKeyFD = currentMapElementCD.getFieldDescriptorByFieldName(mapKeyFieldName); +// if (elementMapKeyFD != null) +// { +// try +// { +// Object key = elementMapKeyFD.getField().get(currentES); +// Map map = (Map) currentFD.automaticLazyGetCollectionOrMap(parentES); +// map.put(key, currentES); +// } +// catch (IllegalArgumentException e) +// { +// this.xmlTranslationException = new SIMPLTranslationException("field not found: " + elementMapKeyFD.getField() + " on " + currentES, e); +// } +// catch (IllegalAccessException e) +// { +// this.xmlTranslationException = new SIMPLTranslationException("cannot access field: " + elementMapKeyFD.getField() + " on " + currentES, e); +// } +// } +// } +// if (mapKeyFieldName == null || elementMapKeyFD == null) +// this.xmlTranslationException = new SIMPLTranslationException("a map element should either implement Mappable or have annotation " + simpl_map_key_field.class.getSimpleName()); +// } +// case COMPOSITE_ELEMENT: +// case COLLECTION_ELEMENT: +// case NAME_SPACE_NESTED_ELEMENT: +// if (parentES != null) +// parentES.createChildHook(currentES); +// else +// debug("cool - post ns element"); +// currentES.deserializationPostHook(); +// if (deserializationHookStrategy != null) +// deserializationHookStrategy.deserializationPostHook(currentES, currentFD); +// this.currentElementState = parentES; +// case NAME_SPACE_SCALAR: +// // case WRAPPER: +// this.currentElementState = parentES; // restore context! +// break; +// default: +// break; +// } +// // end of the Namespace object, so we gotta pop it off, too. +// // if (curentN2JOType == NAME_SPACE_NESTED_ELEMENT) +// // this.currentElementState = this.currentElementState.parent; +// popAndPeekFD(); +// +// if (currentES.parents != null && !currentES.parents.isEmpty() && currentES.parents.size() > 1) +// currentES.parents.pop(); +// // if (this.startElementPushed) // every good push deserves a pop :-) (and othertimes, not!) +// } +// +// /** +// * Assign pending value to a @simpl_scalar +// * +// * @param curentN2JOType +// * @param currentES +// */ +// private void processPendingScalar(final int curentN2JOType, ElementState currentES) +// { +// final int length = currentTextValue.length(); +// if (length > 0) +// { +// try +// { +// switch (curentN2JOType) +// { +// case NAME_SPACE_SCALAR: +// case SCALAR: +// // TODO -- unmarshall to set field with scalar type +// // copy from the StringBuilder +// String value = stringToDeserializeAsScalar(length); +// currentFD.setFieldToScalar(currentES, value, this); +// break; +// case COLLECTION_SCALAR: +// value = stringToDeserializeAsScalar(length); +// currentFD.addLeafNodeToCollection(currentES, value, this); +// break; +// case COMPOSITE_ELEMENT: +// case COLLECTION_ELEMENT: +// case PSEUDO_FIELD_DESCRIPTOR: +// // TODO - is this code used???? +// // optimizations in currentN2JO are for its parent (they were in scope when it was +// // constructed) +// // so we get the optimizations we need from the currentElementState +// // FIXME -- implement this!!! +// FieldDescriptor scalarTextFD = currentElementState.classDescriptor().getScalarTextFD(); +// if (scalarTextFD != null) +// { +// value = stringToDeserializeAsScalar(length); +// scalarTextFD.setFieldToScalar(currentES, value, this); +// } +// break; +// default: +// break; +// } +// } +// catch (SIMPLTranslationException e) +// { +// this.xmlTranslationException = e; +// } +// +// currentTextValue.setLength(0); +// } +// } +// +// /** +// * Get the String that will be marshalled into the value with a ScalarType, using the +// * currentTextValue state variable from the parse, and the length parameter. If appropriate, use +// * the currentFD to perform a regex filter on the value before passing it to the appropriate +// * scalar marshalling and field or collection element setter. +// * +// * @param length +// * @return +// */ +// private String stringToDeserializeAsScalar(final int length) +// { +// String result = new String(currentTextValue.substring(0, length)); +// if (translationScope.isPerformFilters()) +// result = currentFD.filterValue(result); +// return result; +// } +// +// void printStack(String msg) +// { +// currentElementState.debug("Stack -- " + msg + "\t[" + this.currentElementState + "]"); +// for (FieldDescriptor thatFD : fdStack) +// { +// println(thatFD.getTagName() + " - 0x" + Integer.toHexString(thatFD.getType())); +// } +// println(""); +// } +// +// StringBuilder currentTextValue = new StringBuilder(1024); +// +// /** +// * +// * ${tags} +// * +// * @see org.xml.sax.ContentHandler#characters(char[], int, int) +// */ +// public void characters(char[] chars, int startIndex, int length) throws SAXException +// { +// if (xmlTranslationException != null) +// return; +// +// if (currentFD != null) +// { +// int n2joType = currentFD.getType(); +// switch (n2joType) +// { +// case SCALAR: +// case COLLECTION_SCALAR: +// currentTextValue.append(chars, startIndex, length); +// // TODO -- unmarshall to set field with scalar type +// break; +// case COMPOSITE_ELEMENT: +// case COLLECTION_ELEMENT: +// case PSEUDO_FIELD_DESCRIPTOR: +// // optimizations in currentN2JO are for its parent (they were in scope when it was +// // constructed) +// // so we get the optimizations we need from the currentElementState +// if (currentElementState.classDescriptor().hasScalarFD()) +// currentTextValue.append(chars, startIndex, length); +// break; +// default: +// // TODO ?! can we dump characters in this case, or should we append to textNode?! +// // currentElementState.appendLeafXML(buffy, leafElementName, leafValue, needsEscaping, +// // isCDATA) +// break; +// } +// } +// } +// +// /** +// * +// * ${tags} +// * +// * @see org.xml.sax.ContentHandler#endDocument() +// */ +// public void endDocument() throws SAXException +// { +// if ((xmlTranslationException == null) && (root != null)) +// root.deserializationPostHook(); +// } +// +// /** +// * +// * ${tags} +// * +// * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String) +// */ +// public void endPrefixMapping(String prefix) throws SAXException +// { +// // TODO Auto-generated method stub +// +// } +// +// /** +// * +// * ${tags} +// * +// * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int) +// */ +// public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException +// { +// // TODO Auto-generated method stub +// +// } +// +// /** +// * +// * ${tags} +// * +// * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String) +// */ +// public void processingInstruction(String target, String data) throws SAXException +// { +// // TODO Auto-generated method stub +// +// } +// +// /** +// * +// * ${tags} +// * +// * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator) +// */ +// public void setDocumentLocator(Locator locator) +// { +// // TODO Auto-generated method stub +// +// } +// +// /** +// * +// * ${tags} +// * +// * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String) +// */ +// public void skippedEntity(String name) throws SAXException +// { +// // TODO Auto-generated method stub +// +// } +// +// /** +// * +// * ${tags} +// * +// * @see org.xml.sax.ContentHandler#startDocument() +// */ +// public void startDocument() throws SAXException +// { +// // TODO Auto-generated method stub +// +// } +// +// /** +// * +// * ${tags} +// * +// * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) +// */ +// public void startPrefixMapping(String nsID, String urn) throws SAXException +// { +// // debug("Hi: startPrefixMapping(" + nsID +" := " + urn); +// // this.nameSpacePrefix = prefix; +// // this.nameSpaceURN = urn; +// if (nsID.length() > 0) // these days, ignore ns decls without an id (default ones) +// { +// // push the urn in first; pop it off 2nd +// xmlnsStack.add(urn); +// // push the nsID in 2nd; pop it off 1st +// xmlnsStack.add(nsID); +// } +// } +// +// // String nameSpacePrefix; +// // +// // String nameSpaceURN; //FIXME -- this should be a stack! +// +// ArrayList xmlnsStack = new ArrayList(2); +// +// void registerXMLNS() +// { +// int size = xmlnsStack.size(); +// while (size >= 2) +// { +// String nameSpaceID = xmlnsStack.remove(--size); +// String urn = xmlnsStack.remove(--size); +// if ((nameSpaceID != null) && (urn != null)) +// { +// registerXMLNS(this.currentElementState, nameSpaceID, urn); +// } +// } +// // String urn = nameSpaceURN; +// // if (urn != null) +// // { +// // registerXMLNS(this.currentElementState, nameSpacePrefix, urn); +// // nameSpaceURN = null; +// // nameSpacePrefix = null; +// // } +// } +// +// /** +// * Create a name space object, nested in the context, using info saved in this. +// * +// * @param context +// * @param urn +// * The value of the xmlns:id attribute is the URL that is mapped to the class. +// */ +// private void registerXMLNS(ElementState context, String prefix, String urn) +// { +// if (context != null) +// context.classDescriptor().mapNamespaceIdToClass(translationScope, prefix, urn); +// else +// println("ERROR: Null context. Can't register xmlns:" + prefix + "=" + urn); +// } +// +// /** +// * @return the root +// */ +// public ElementState root() +// { +// return root; +// } +// +// public File fileContext() +// { +// return (fileContext != null) ? fileContext : (purlContext != null) ? purlContext.file() : null; +// } +// +// public ParsedURL purlContext() +// { +// return (purlContext != null) ? purlContext : (fileContext != null) ? new ParsedURL(fileContext) +// : null; +// } +// +} diff --git a/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateTLVHandler.java b/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateTLVHandler.java index 11dadd34..cb824aaf 100644 --- a/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateTLVHandler.java +++ b/simplCore/src/ecologylab/serialization/deserializers/pushhandlers/ElementStateTLVHandler.java @@ -1,519 +1,519 @@ -package ecologylab.serialization.deserializers.pushhandlers; -// -//import java.io.File; -//import java.util.ArrayList; -//import java.util.Collection; -//import java.util.Map; -// -//import ecologylab.generic.Debug; -//import ecologylab.net.ParsedURL; -//import ecologylab.serialization.ClassDescriptor; -//import ecologylab.serialization.DeserializationHookStrategy; -//import ecologylab.serialization.ElementState; -//import ecologylab.serialization.FieldDescriptor; -//import ecologylab.serialization.FieldTypes; -//import ecologylab.serialization.RootElementException; -//import ecologylab.serialization.SIMPLTranslationException; -//import ecologylab.serialization.ScalarUnmarshallingContext; -//import ecologylab.serialization.TranslationScope; -//import ecologylab.serialization.deserializers.parsers.tlv.TLVEvents; -//import ecologylab.serialization.deserializers.parsers.tlv.TLVParser; -//import ecologylab.serialization.types.element.IMappable; -// -public class ElementStateTLVHandler // extends Debug implements TLVEvents, FieldTypes, ScalarUnmarshallingContext -{ -// TranslationScope translationScope; -// -// TLVParser tlvParser = null; -// -// ElementState root; -// -// ElementState currentElementState; -// -// FieldDescriptor currentFD; -// -// private SIMPLTranslationException tlvTranslationException; -// -// ArrayList fdStack = new ArrayList(); -// -// ParsedURL purlContext; -// -// File fileContext; -// -// DeserializationHookStrategy deserializationHookStrategy; -// -// public ElementStateTLVHandler(TranslationScope translationScope) -// { -// this.translationScope = translationScope; -// tlvParser = new TLVParser(this, translationScope); -// } -// -// public ElementState parse(CharSequence charSequence) -// { -// return parse(charSequence.toString().getBytes()); -// } -// -// public ElementState parse(byte[] byteArray) -// { -// tlvParser.parse(byteArray); -// return root; -// } -// -// @Override -// public void endObject(String objectName) -// { -// if (tlvTranslationException != null) -// return; -// -// FieldDescriptor currentFD = this.currentFD; -// final int curentFdType = currentFD.getType(); -// -// ElementState currentES = this.currentElementState; -// processPendingScalar(curentFdType, currentES); -// -// final ElementState parentES; -// -// if (currentES.parents == null || currentES.parents.isEmpty()) -// parentES = currentES.parent; -// else -// parentES = currentES.parents.peek(); -// -// switch (curentFdType) -// // every good push deserves a pop :-) (and othertimes, not!) -// { -// case MAP_ELEMENT: -// if (currentES instanceof IMappable) -// { -// final Object key = ((IMappable) currentES).key(); -// Map map = (Map) currentFD.automaticLazyGetCollectionOrMap(parentES); -// // Map map = currentFD.getMap(parentES); -// map.put(key, currentES); -// } -// case COMPOSITE_ELEMENT: -// case COLLECTION_ELEMENT: -// case NAME_SPACE_NESTED_ELEMENT: -// if (parentES != null) -// parentES.createChildHook(currentES); -// else -// debug("cool - post ns element"); -// currentES.deserializationPostHook(); -// if (deserializationHookStrategy != null) -// deserializationHookStrategy.deserializationPostHook(currentES, currentFD); -// this.currentElementState = currentES.parent; -// case NAME_SPACE_SCALAR: -// // case WRAPPER: -// this.currentElementState = parentES; // restore context! -// break; -// default: -// break; -// } -// // end of the Namespace object, so we gotta pop it off, too. -// // if (curentN2JOType == NAME_SPACE_NESTED_ELEMENT) -// // this.currentElementState = this.currentElementState.parent; -// popAndPeekFD(); -// -// if (currentES.parents != null && !currentES.parents.isEmpty() && currentES.parents.size() > 1) -// currentES.parents.pop(); -// } -// -// @Override -// public void endTLV() -// { -// if ((tlvTranslationException == null) && (root != null)) -// root.deserializationPostHook(); -// -// } -// -// StringBuilder currentTextValue = new StringBuilder(1024); -// -// @Override -// public void primitive(String value) -// { -// if (tlvTranslationException != null) -// return; -// -// if (currentFD != null) -// { -// int n2joType = currentFD.getType(); -// switch (n2joType) -// { -// case SCALAR: -// case COLLECTION_SCALAR: -// currentTextValue.append(value); -// processPendingScalar(n2joType, currentElementState); -// // TODO -- unmarshall to set field with scalar type -// break; -// case COMPOSITE_ELEMENT: -// case COLLECTION_ELEMENT: -// case PSEUDO_FIELD_DESCRIPTOR: -// // optimizations in currentN2JO are for its parent (they were in scope when it was -// // constructed) -// // so we get the optimizations we need from the currentElementState -// if (currentElementState.classDescriptor().hasScalarFD()) -// currentTextValue.append(value.toString()); -// break; -// default: -// // TODO ?! can we dump characters in this case, or should we append to textNode?! -// // currentElementState.appendLeafXML(buffy, leafElementName, leafValue, needsEscaping, -// // isCDATA) -// break; -// } -// } -// -// } -// -// @Override -// public void startObject(String objectName) -// { -// if (tlvTranslationException != null) -// return; -// -// FieldDescriptor childFD = null; -// final boolean isRoot = (root == null); -// if (isRoot) -// { // form the root ElementState! -// ClassDescriptor rootClassDescriptor = translationScope.getClassDescriptorByTag(objectName); -// if (rootClassDescriptor != null) -// { -// try -// { -// ElementState root = null; -// if (root == null) -// root = rootClassDescriptor.getInstance(); -// if (root != null) -// { -// root.setupRoot(); -// setRoot(root); -// if (deserializationHookStrategy != null) -// deserializationHookStrategy.deserializationPreHook(root, null); -// -// childFD = rootClassDescriptor.pseudoFieldDescriptor(); -// } -// else -// { -// this.tlvTranslationException = new RootElementException(objectName, translationScope); -// return; -// } -// } -// catch (SIMPLTranslationException e) -// { -// tlvTranslationException = e; -// } -// } -// else -// { -// // else, we dont translate this element; we ignore it. -// String message = "TLV Translation WARNING: Cant find class object for Root JSON element <" -// + objectName + ">: Ignored. "; -// println(message); -// tlvTranslationException = new SIMPLTranslationException(message); -// return; -// } -// } -// else -// // not root -// { -// final int currentType = currentFD.getType(); -// ElementState currentES = this.currentElementState; -// // if there is a pending text node, assign it somehow! -// processPendingScalar(currentType, currentES); -// -// ClassDescriptor currentClassDescriptor = currentClassDescriptor(); -// childFD = (currentFD != null) && (currentType == IGNORED_ELEMENT) ? -// // new NodeToJavaOptimizations(tagName) : // (nice for debugging; slows us down) -// FieldDescriptor.IGNORED_ELEMENT_FIELD_DESCRIPTOR -// : (currentType == WRAPPER) ? currentFD.getWrappedFD() : currentClassDescriptor -// .getFieldDescriptorByTag(objectName, translationScope, currentES); -// if (childFD == null) -// { -// childFD = makeIgnoredFieldDescriptor(objectName, currentClassDescriptor); -// } -// } -// this.currentFD = childFD; -// // TODO? -- do we need to avoid this if null from an exception in translating root? -// pushFD(childFD); -// // printStack("After push"); -// -// if (isRoot) -// return; -// -// ElementState currentElementState = this.currentElementState; -// ElementState childES = null; -// try -// { -// switch (childFD.getType()) -// { -// case COMPOSITE_ELEMENT: -// childES = childFD.constructChildElementState(currentElementState, objectName); -// -// if (childES == null) -// { -// childFD = makeIgnoredFieldDescriptor(objectName, currentClassDescriptor()); -// } -// else -// childFD.setFieldToComposite(currentElementState, childES); // maybe we -// // should do -// // this on close -// // element -// break; -// case SCALAR: -// // wait for characters to set scalar field -// // activeN2JO.setScalarFieldWithLeafNode(activeES, childNode); -// break; -// case COLLECTION_ELEMENT: -// -// Collection collection = (Collection) childFD -// .automaticLazyGetCollectionOrMap(currentElementState); -// if (collection != null) -// { -// ElementState childElement = childFD.constructChildElementState(currentElementState, -// objectName); -// childES = childElement; -// -// if (childES == null) -// { -// childFD = makeIgnoredFieldDescriptor(objectName, currentClassDescriptor()); -// } -// -// collection.add(childES); -// } -// // activeNJO.formElementAndAddToCollection(activeES, childNode); -// break; -// case COLLECTION_SCALAR: -// // wait for characters to create scalar reference type and add to collection -// // activeN2JO.addLeafNodeToCollection(activeES, childNode); -// break; -// case MAP_ELEMENT: -// Map map = (Map) childFD.automaticLazyGetCollectionOrMap(currentElementState); -// if (map != null) -// { -// ElementState childElement = childFD.constructChildElementState(currentElementState, -// objectName); -// -// childES = childElement; -// if (childES == null) -// { -// this.currentFD = makeIgnoredFieldDescriptor(objectName, currentClassDescriptor()); -// } -// } -// // Map map = activeFieldDescriptor.getMap(currentElementState); -// // if (map != null) -// // { -// // childES = activeFieldDescriptor.constructChildElementState(currentElementState, tagName); -// // } -// break; -// case IGNORED_ELEMENT: -// // should get a set of Optimizations for this, to represent its subfields -// case BAD_FIELD: -// case WRAPPER: -// default: -// break; -// -// } -// if (childES != null) -// { -// // fill in its attributes -// if (deserializationHookStrategy != null) -// deserializationHookStrategy.deserializationPreHook(childES, childFD); -// -// this.currentElementState = childES; // childES.parent = old currentElementState -// this.currentFD = childFD; -// } -// } -// catch (SIMPLTranslationException e) -// { -// this.tlvTranslationException = e; -// } -// -// } -// -// private void setRoot(ElementState root) -// { -// this.root = root; -// this.currentElementState = root; -// } -// -// private ClassDescriptor currentClassDescriptor() -// { -// if (currentElementState != null) -// return this.currentElementState.classDescriptor(); -// else -// return null; -// } -// -// private void pushFD(FieldDescriptor fd) -// { -// this.fdStack.add(fd); -// } -// -// private void popAndPeekFD() -// { -// ArrayList stack = this.fdStack; -// int last = stack.size() - 1; -// if (last >= 0) -// { -// FieldDescriptor result = stack.remove(last--); -// if (last >= 0) -// result = stack.get(last); -// this.currentFD = result; -// // printStack("After Pop"); -// } -// } -// -// /** -// * Assign pending value to a @simpl_scalar -// * -// * @param curentN2JOType -// * @param currentES -// */ -// private void processPendingScalar(final int curentN2JOType, ElementState currentES) -// { -// final int length = currentTextValue.length(); -// if (length > 0) -// { -// try -// { -// switch (curentN2JOType) -// { -// case NAME_SPACE_SCALAR: -// case SCALAR: -// // TODO -- unmarshall to set field with scalar type -// // copy from the StringBuilder -// String value = stringToDeserializeAsScalar(length); -// currentFD.setFieldToScalar(currentES, value, this); -// break; -// case COLLECTION_SCALAR: -// value = stringToDeserializeAsScalar(length); -// currentFD.addLeafNodeToCollection(currentES, value, this); -// break; -// case COMPOSITE_ELEMENT: -// case COLLECTION_ELEMENT: -// case PSEUDO_FIELD_DESCRIPTOR: -// // TODO - is this code used???? -// // optimizations in currentN2JO are for its parent (they were in scope when it was -// // constructed) -// // so we get the optimizations we need from the currentElementState -// // FIXME -- implement this!!! -// FieldDescriptor scalarTextFD = currentElementState.classDescriptor().getScalarTextFD(); -// if (scalarTextFD != null) -// { -// value = stringToDeserializeAsScalar(length); -// scalarTextFD.setFieldToScalar(currentES, value, this); -// } -// break; -// default: -// break; -// } -// } -// catch (SIMPLTranslationException e) -// { -// this.tlvTranslationException = e; -// } -// -// currentTextValue.setLength(0); -// } -// } -// -// private FieldDescriptor makeIgnoredFieldDescriptor(String key, -// ClassDescriptor currentClassDescriptor) -// { -// FieldDescriptor activeFieldDescriptor; -// currentClassDescriptor.warning(" Ignoring key <" + key + ">"); -// activeFieldDescriptor = new FieldDescriptor(key); // TODO -- should we record -// // declaringClass in here??! -// if (activeFieldDescriptor.getTagName() != null) -// currentClassDescriptor.addFieldDescriptorMapping(activeFieldDescriptor); -// return activeFieldDescriptor; -// } -// -// /** -// * Get the String that will be marshalled into the value with a ScalarType, using the -// * currentTextValue state variable from the parse, and the length parameter. If appropriate, use -// * the currentFD to perform a regex filter on the value before passing it to the appropriate -// * scalar marshalling and field or collection element setter. -// * -// * @param length -// * @return -// */ -// private String stringToDeserializeAsScalar(final int length) -// { -// String result = new String(currentTextValue.substring(0, length)); -// if (translationScope.isPerformFilters()) -// result = currentFD.filterValue(result); -// return result; -// } -// -// @Override -// public void startTLV() -// { -// // TODO Auto-generated method stub -// -// } -// -// /** -// * @return the root -// */ -// public ElementState root() -// { -// return root; -// } -// -// public File fileContext() -// { -// return (fileContext != null) ? fileContext : (purlContext != null) ? purlContext.file() : null; -// } -// -// public ParsedURL purlContext() -// { -// return purlContext; -// } -// // -// // @Override -// // public void endObject(String objectName) -// // { -// // System.out.println("END of object : " + objectName); -// // -// // } -// // -// // @Override -// // public void endTLV() -// // { -// // System.out.println("end of tlv message "); -// // -// // } -// // -// // @Override -// // public void primitive(String value) -// // { -// // System.out.println("value of object : " + value); -// // -// // } -// // -// // @Override -// // public void startObject(String objectName) -// // { -// // System.out.println("START of object : " + objectName); -// // -// // } -// // -// // @Override -// // public void startTLV() -// // { -// // System.out.println("start of tlv message "); -// // -// // } -// // -// // @Override -// // public File fileContext() -// // { -// // // TODO Auto-generated method stub -// // return null; -// // } -// // -// // @Override -// // public ParsedURL purlContext() -// // { -// // // TODO Auto-generated method stub -// // return null; -// // } -} +package ecologylab.serialization.deserializers.pushhandlers; +// +//import java.io.File; +//import java.util.ArrayList; +//import java.util.Collection; +//import java.util.Map; +// +//import ecologylab.generic.Debug; +//import ecologylab.net.ParsedURL; +//import ecologylab.serialization.ClassDescriptor; +//import ecologylab.serialization.DeserializationHookStrategy; +//import ecologylab.serialization.ElementState; +//import ecologylab.serialization.FieldDescriptor; +//import ecologylab.serialization.FieldTypes; +//import ecologylab.serialization.RootElementException; +//import ecologylab.serialization.SIMPLTranslationException; +//import ecologylab.serialization.ScalarUnmarshallingContext; +//import ecologylab.serialization.TranslationScope; +//import ecologylab.serialization.deserializers.parsers.tlv.TLVEvents; +//import ecologylab.serialization.deserializers.parsers.tlv.TLVParser; +//import ecologylab.serialization.types.element.IMappable; +// +public class ElementStateTLVHandler // extends Debug implements TLVEvents, FieldTypes, ScalarUnmarshallingContext +{ +// TranslationScope translationScope; +// +// TLVParser tlvParser = null; +// +// ElementState root; +// +// ElementState currentElementState; +// +// FieldDescriptor currentFD; +// +// private SIMPLTranslationException tlvTranslationException; +// +// ArrayList fdStack = new ArrayList(); +// +// ParsedURL purlContext; +// +// File fileContext; +// +// DeserializationHookStrategy deserializationHookStrategy; +// +// public ElementStateTLVHandler(TranslationScope translationScope) +// { +// this.translationScope = translationScope; +// tlvParser = new TLVParser(this, translationScope); +// } +// +// public ElementState parse(CharSequence charSequence) +// { +// return parse(charSequence.toString().getBytes()); +// } +// +// public ElementState parse(byte[] byteArray) +// { +// tlvParser.parse(byteArray); +// return root; +// } +// +// @Override +// public void endObject(String objectName) +// { +// if (tlvTranslationException != null) +// return; +// +// FieldDescriptor currentFD = this.currentFD; +// final int curentFdType = currentFD.getType(); +// +// ElementState currentES = this.currentElementState; +// processPendingScalar(curentFdType, currentES); +// +// final ElementState parentES; +// +// if (currentES.parents == null || currentES.parents.isEmpty()) +// parentES = currentES.parent; +// else +// parentES = currentES.parents.peek(); +// +// switch (curentFdType) +// // every good push deserves a pop :-) (and othertimes, not!) +// { +// case MAP_ELEMENT: +// if (currentES instanceof IMappable) +// { +// final Object key = ((IMappable) currentES).key(); +// Map map = (Map) currentFD.automaticLazyGetCollectionOrMap(parentES); +// // Map map = currentFD.getMap(parentES); +// map.put(key, currentES); +// } +// case COMPOSITE_ELEMENT: +// case COLLECTION_ELEMENT: +// case NAME_SPACE_NESTED_ELEMENT: +// if (parentES != null) +// parentES.createChildHook(currentES); +// else +// debug("cool - post ns element"); +// currentES.deserializationPostHook(); +// if (deserializationHookStrategy != null) +// deserializationHookStrategy.deserializationPostHook(currentES, currentFD); +// this.currentElementState = currentES.parent; +// case NAME_SPACE_SCALAR: +// // case WRAPPER: +// this.currentElementState = parentES; // restore context! +// break; +// default: +// break; +// } +// // end of the Namespace object, so we gotta pop it off, too. +// // if (curentN2JOType == NAME_SPACE_NESTED_ELEMENT) +// // this.currentElementState = this.currentElementState.parent; +// popAndPeekFD(); +// +// if (currentES.parents != null && !currentES.parents.isEmpty() && currentES.parents.size() > 1) +// currentES.parents.pop(); +// } +// +// @Override +// public void endTLV() +// { +// if ((tlvTranslationException == null) && (root != null)) +// root.deserializationPostHook(); +// +// } +// +// StringBuilder currentTextValue = new StringBuilder(1024); +// +// @Override +// public void primitive(String value) +// { +// if (tlvTranslationException != null) +// return; +// +// if (currentFD != null) +// { +// int n2joType = currentFD.getType(); +// switch (n2joType) +// { +// case SCALAR: +// case COLLECTION_SCALAR: +// currentTextValue.append(value); +// processPendingScalar(n2joType, currentElementState); +// // TODO -- unmarshall to set field with scalar type +// break; +// case COMPOSITE_ELEMENT: +// case COLLECTION_ELEMENT: +// case PSEUDO_FIELD_DESCRIPTOR: +// // optimizations in currentN2JO are for its parent (they were in scope when it was +// // constructed) +// // so we get the optimizations we need from the currentElementState +// if (currentElementState.classDescriptor().hasScalarFD()) +// currentTextValue.append(value.toString()); +// break; +// default: +// // TODO ?! can we dump characters in this case, or should we append to textNode?! +// // currentElementState.appendLeafXML(buffy, leafElementName, leafValue, needsEscaping, +// // isCDATA) +// break; +// } +// } +// +// } +// +// @Override +// public void startObject(String objectName) +// { +// if (tlvTranslationException != null) +// return; +// +// FieldDescriptor childFD = null; +// final boolean isRoot = (root == null); +// if (isRoot) +// { // form the root ElementState! +// ClassDescriptor rootClassDescriptor = translationScope.getClassDescriptorByTag(objectName); +// if (rootClassDescriptor != null) +// { +// try +// { +// ElementState root = null; +// if (root == null) +// root = rootClassDescriptor.getInstance(); +// if (root != null) +// { +// root.setupRoot(); +// setRoot(root); +// if (deserializationHookStrategy != null) +// deserializationHookStrategy.deserializationPreHook(root, null); +// +// childFD = rootClassDescriptor.pseudoFieldDescriptor(); +// } +// else +// { +// this.tlvTranslationException = new RootElementException(objectName, translationScope); +// return; +// } +// } +// catch (SIMPLTranslationException e) +// { +// tlvTranslationException = e; +// } +// } +// else +// { +// // else, we dont translate this element; we ignore it. +// String message = "TLV Translation WARNING: Cant find class object for Root JSON element <" +// + objectName + ">: Ignored. "; +// println(message); +// tlvTranslationException = new SIMPLTranslationException(message); +// return; +// } +// } +// else +// // not root +// { +// final int currentType = currentFD.getType(); +// ElementState currentES = this.currentElementState; +// // if there is a pending text node, assign it somehow! +// processPendingScalar(currentType, currentES); +// +// ClassDescriptor currentClassDescriptor = currentClassDescriptor(); +// childFD = (currentFD != null) && (currentType == IGNORED_ELEMENT) ? +// // new NodeToJavaOptimizations(tagName) : // (nice for debugging; slows us down) +// FieldDescriptor.IGNORED_ELEMENT_FIELD_DESCRIPTOR +// : (currentType == WRAPPER) ? currentFD.getWrappedFD() : currentClassDescriptor +// .getFieldDescriptorByTag(objectName, translationScope, currentES); +// if (childFD == null) +// { +// childFD = makeIgnoredFieldDescriptor(objectName, currentClassDescriptor); +// } +// } +// this.currentFD = childFD; +// // TODO? -- do we need to avoid this if null from an exception in translating root? +// pushFD(childFD); +// // printStack("After push"); +// +// if (isRoot) +// return; +// +// ElementState currentElementState = this.currentElementState; +// ElementState childES = null; +// try +// { +// switch (childFD.getType()) +// { +// case COMPOSITE_ELEMENT: +// childES = childFD.constructChildElementState(currentElementState, objectName); +// +// if (childES == null) +// { +// childFD = makeIgnoredFieldDescriptor(objectName, currentClassDescriptor()); +// } +// else +// childFD.setFieldToComposite(currentElementState, childES); // maybe we +// // should do +// // this on close +// // element +// break; +// case SCALAR: +// // wait for characters to set scalar field +// // activeN2JO.setScalarFieldWithLeafNode(activeES, childNode); +// break; +// case COLLECTION_ELEMENT: +// +// Collection collection = (Collection) childFD +// .automaticLazyGetCollectionOrMap(currentElementState); +// if (collection != null) +// { +// ElementState childElement = childFD.constructChildElementState(currentElementState, +// objectName); +// childES = childElement; +// +// if (childES == null) +// { +// childFD = makeIgnoredFieldDescriptor(objectName, currentClassDescriptor()); +// } +// +// collection.add(childES); +// } +// // activeNJO.formElementAndAddToCollection(activeES, childNode); +// break; +// case COLLECTION_SCALAR: +// // wait for characters to create scalar reference type and add to collection +// // activeN2JO.addLeafNodeToCollection(activeES, childNode); +// break; +// case MAP_ELEMENT: +// Map map = (Map) childFD.automaticLazyGetCollectionOrMap(currentElementState); +// if (map != null) +// { +// ElementState childElement = childFD.constructChildElementState(currentElementState, +// objectName); +// +// childES = childElement; +// if (childES == null) +// { +// this.currentFD = makeIgnoredFieldDescriptor(objectName, currentClassDescriptor()); +// } +// } +// // Map map = activeFieldDescriptor.getMap(currentElementState); +// // if (map != null) +// // { +// // childES = activeFieldDescriptor.constructChildElementState(currentElementState, tagName); +// // } +// break; +// case IGNORED_ELEMENT: +// // should get a set of Optimizations for this, to represent its subfields +// case BAD_FIELD: +// case WRAPPER: +// default: +// break; +// +// } +// if (childES != null) +// { +// // fill in its attributes +// if (deserializationHookStrategy != null) +// deserializationHookStrategy.deserializationPreHook(childES, childFD); +// +// this.currentElementState = childES; // childES.parent = old currentElementState +// this.currentFD = childFD; +// } +// } +// catch (SIMPLTranslationException e) +// { +// this.tlvTranslationException = e; +// } +// +// } +// +// private void setRoot(ElementState root) +// { +// this.root = root; +// this.currentElementState = root; +// } +// +// private ClassDescriptor currentClassDescriptor() +// { +// if (currentElementState != null) +// return this.currentElementState.classDescriptor(); +// else +// return null; +// } +// +// private void pushFD(FieldDescriptor fd) +// { +// this.fdStack.add(fd); +// } +// +// private void popAndPeekFD() +// { +// ArrayList stack = this.fdStack; +// int last = stack.size() - 1; +// if (last >= 0) +// { +// FieldDescriptor result = stack.remove(last--); +// if (last >= 0) +// result = stack.get(last); +// this.currentFD = result; +// // printStack("After Pop"); +// } +// } +// +// /** +// * Assign pending value to a @simpl_scalar +// * +// * @param curentN2JOType +// * @param currentES +// */ +// private void processPendingScalar(final int curentN2JOType, ElementState currentES) +// { +// final int length = currentTextValue.length(); +// if (length > 0) +// { +// try +// { +// switch (curentN2JOType) +// { +// case NAME_SPACE_SCALAR: +// case SCALAR: +// // TODO -- unmarshall to set field with scalar type +// // copy from the StringBuilder +// String value = stringToDeserializeAsScalar(length); +// currentFD.setFieldToScalar(currentES, value, this); +// break; +// case COLLECTION_SCALAR: +// value = stringToDeserializeAsScalar(length); +// currentFD.addLeafNodeToCollection(currentES, value, this); +// break; +// case COMPOSITE_ELEMENT: +// case COLLECTION_ELEMENT: +// case PSEUDO_FIELD_DESCRIPTOR: +// // TODO - is this code used???? +// // optimizations in currentN2JO are for its parent (they were in scope when it was +// // constructed) +// // so we get the optimizations we need from the currentElementState +// // FIXME -- implement this!!! +// FieldDescriptor scalarTextFD = currentElementState.classDescriptor().getScalarTextFD(); +// if (scalarTextFD != null) +// { +// value = stringToDeserializeAsScalar(length); +// scalarTextFD.setFieldToScalar(currentES, value, this); +// } +// break; +// default: +// break; +// } +// } +// catch (SIMPLTranslationException e) +// { +// this.tlvTranslationException = e; +// } +// +// currentTextValue.setLength(0); +// } +// } +// +// private FieldDescriptor makeIgnoredFieldDescriptor(String key, +// ClassDescriptor currentClassDescriptor) +// { +// FieldDescriptor activeFieldDescriptor; +// currentClassDescriptor.warning(" Ignoring key <" + key + ">"); +// activeFieldDescriptor = new FieldDescriptor(key); // TODO -- should we record +// // declaringClass in here??! +// if (activeFieldDescriptor.getTagName() != null) +// currentClassDescriptor.addFieldDescriptorMapping(activeFieldDescriptor); +// return activeFieldDescriptor; +// } +// +// /** +// * Get the String that will be marshalled into the value with a ScalarType, using the +// * currentTextValue state variable from the parse, and the length parameter. If appropriate, use +// * the currentFD to perform a regex filter on the value before passing it to the appropriate +// * scalar marshalling and field or collection element setter. +// * +// * @param length +// * @return +// */ +// private String stringToDeserializeAsScalar(final int length) +// { +// String result = new String(currentTextValue.substring(0, length)); +// if (translationScope.isPerformFilters()) +// result = currentFD.filterValue(result); +// return result; +// } +// +// @Override +// public void startTLV() +// { +// // TODO Auto-generated method stub +// +// } +// +// /** +// * @return the root +// */ +// public ElementState root() +// { +// return root; +// } +// +// public File fileContext() +// { +// return (fileContext != null) ? fileContext : (purlContext != null) ? purlContext.file() : null; +// } +// +// public ParsedURL purlContext() +// { +// return purlContext; +// } +// // +// // @Override +// // public void endObject(String objectName) +// // { +// // System.out.println("END of object : " + objectName); +// // +// // } +// // +// // @Override +// // public void endTLV() +// // { +// // System.out.println("end of tlv message "); +// // +// // } +// // +// // @Override +// // public void primitive(String value) +// // { +// // System.out.println("value of object : " + value); +// // +// // } +// // +// // @Override +// // public void startObject(String objectName) +// // { +// // System.out.println("START of object : " + objectName); +// // +// // } +// // +// // @Override +// // public void startTLV() +// // { +// // System.out.println("start of tlv message "); +// // +// // } +// // +// // @Override +// // public File fileContext() +// // { +// // // TODO Auto-generated method stub +// // return null; +// // } +// // +// // @Override +// // public ParsedURL purlContext() +// // { +// // // TODO Auto-generated method stub +// // return null; +// // } +} diff --git a/simplCore/src/ecologylab/serialization/formatenums/BinaryFormat.java b/simplCore/src/ecologylab/serialization/formatenums/BinaryFormat.java index 16fde4c7..3b411fe7 100644 --- a/simplCore/src/ecologylab/serialization/formatenums/BinaryFormat.java +++ b/simplCore/src/ecologylab/serialization/formatenums/BinaryFormat.java @@ -1,6 +1,6 @@ -package ecologylab.serialization.formatenums; - -public enum BinaryFormat -{ - TLV; -} +package ecologylab.serialization.formatenums; + +public enum BinaryFormat +{ + TLV; +} diff --git a/simplCore/src/ecologylab/serialization/formatenums/Format.java b/simplCore/src/ecologylab/serialization/formatenums/Format.java index ea67f3b8..fa5266fc 100644 --- a/simplCore/src/ecologylab/serialization/formatenums/Format.java +++ b/simplCore/src/ecologylab/serialization/formatenums/Format.java @@ -1,6 +1,6 @@ -package ecologylab.serialization.formatenums; - -public enum Format -{ - XML, JSON, TLV, YAML, BIBTEX; -} +package ecologylab.serialization.formatenums; + +public enum Format +{ + XML, JSON, TLV, YAML, BIBTEX; +} diff --git a/simplCore/src/ecologylab/serialization/formatenums/StringFormat.java b/simplCore/src/ecologylab/serialization/formatenums/StringFormat.java index 1c65aa98..4a0c2b59 100644 --- a/simplCore/src/ecologylab/serialization/formatenums/StringFormat.java +++ b/simplCore/src/ecologylab/serialization/formatenums/StringFormat.java @@ -1,6 +1,6 @@ -package ecologylab.serialization.formatenums; - -public enum StringFormat -{ - XML, JSON, YAML, BIBTEX -} +package ecologylab.serialization.formatenums; + +public enum StringFormat +{ + XML, JSON, YAML, BIBTEX +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/ArrayProperty.java b/simplCore/src/ecologylab/serialization/library/apple/ArrayProperty.java index 02c66980..2de63825 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/ArrayProperty.java +++ b/simplCore/src/ecologylab/serialization/library/apple/ArrayProperty.java @@ -1,39 +1,39 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -import java.util.List; - -import ecologylab.serialization.annotations.simpl_classes; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_inherit -@simpl_tag("array") -public class ArrayProperty extends Property -{ - @simpl_collection - @simpl_nowrap - @simpl_classes( - { DictionaryProperty.class, StringProperty.class, ArrayProperty.class, RealProperty.class }) - List dictionaries; - - /** - * - */ - public ArrayProperty() - { - // TODO Auto-generated constructor stub - } - - public List getPropertyList() - { - return this.dictionaries; - } -} +/** + * + */ +package ecologylab.serialization.library.apple; + +import java.util.List; + +import ecologylab.serialization.annotations.simpl_classes; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_inherit +@simpl_tag("array") +public class ArrayProperty extends Property +{ + @simpl_collection + @simpl_nowrap + @simpl_classes( + { DictionaryProperty.class, StringProperty.class, ArrayProperty.class, RealProperty.class }) + List dictionaries; + + /** + * + */ + public ArrayProperty() + { + // TODO Auto-generated constructor stub + } + + public List getPropertyList() + { + return this.dictionaries; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/BooleanProperty.java b/simplCore/src/ecologylab/serialization/library/apple/BooleanProperty.java index 3bd4e0af..f52cab70 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/BooleanProperty.java +++ b/simplCore/src/ecologylab/serialization/library/apple/BooleanProperty.java @@ -1,21 +1,21 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class BooleanProperty extends Property -{ - boolean contents; - - /** - * - */ - public BooleanProperty() - { - // TODO Auto-generated constructor stub - } - -} +/** + * + */ +package ecologylab.serialization.library.apple; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class BooleanProperty extends Property +{ + boolean contents; + + /** + * + */ + public BooleanProperty() + { + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/DataProperty.java b/simplCore/src/ecologylab/serialization/library/apple/DataProperty.java index 65458ffc..73e1baf2 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/DataProperty.java +++ b/simplCore/src/ecologylab/serialization/library/apple/DataProperty.java @@ -1,32 +1,32 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_tag("data") -@simpl_inherit -public class DataProperty extends Property -{ - @simpl_hints( - { Hint.XML_TEXT }) - @simpl_scalar - String contents; - - /** - * - */ - public DataProperty() - { - // TODO Auto-generated constructor stub - } - -} +/** + * + */ +package ecologylab.serialization.library.apple; + +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_tag("data") +@simpl_inherit +public class DataProperty extends Property +{ + @simpl_hints( + { Hint.XML_TEXT }) + @simpl_scalar + String contents; + + /** + * + */ + public DataProperty() + { + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/DictionaryProperty.java b/simplCore/src/ecologylab/serialization/library/apple/DictionaryProperty.java index f9d0ac5c..0e0bdadd 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/DictionaryProperty.java +++ b/simplCore/src/ecologylab/serialization/library/apple/DictionaryProperty.java @@ -1,69 +1,69 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_classes; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.deserializers.ISimplDeserializationPost; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_tag("dict") -@simpl_inherit -public class DictionaryProperty extends Property implements ISimplDeserializationPost -{ - @simpl_collection - @simpl_nowrap - @simpl_classes( - { DictionaryProperty.class, StringProperty.class, KeyProperty.class, ArrayProperty.class, - IntegerProperty.class, TrueProperty.class, FalseProperty.class, RealProperty.class, - DataProperty.class }) - List properties; - - /** - * Not currently serialized; used for access only. - */ - Map propertyMap; - - public DictionaryProperty() - { - - } - - @Override - public void deserializationPostHook(TranslationContext translationContext, Object object) - { - debug("deser post hook!"); - propertyMap = new HashMap(); - - Iterator propertyIter = properties.iterator(); - - while (propertyIter.hasNext()) - { - KeyProperty key = (KeyProperty) propertyIter.next(); - Property value = propertyIter.next(); - - String temp = key.getContents(); - - propertyMap.put(key.getContents(), value); - } - - debug("done desr"); - } - - public Property getProperty(String key) - { - return this.propertyMap.get(key); - } -} +/** + * + */ +package ecologylab.serialization.library.apple; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_classes; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.deserializers.ISimplDeserializationPost; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_tag("dict") +@simpl_inherit +public class DictionaryProperty extends Property implements ISimplDeserializationPost +{ + @simpl_collection + @simpl_nowrap + @simpl_classes( + { DictionaryProperty.class, StringProperty.class, KeyProperty.class, ArrayProperty.class, + IntegerProperty.class, TrueProperty.class, FalseProperty.class, RealProperty.class, + DataProperty.class }) + List properties; + + /** + * Not currently serialized; used for access only. + */ + Map propertyMap; + + public DictionaryProperty() + { + + } + + @Override + public void deserializationPostHook(TranslationContext translationContext, Object object) + { + debug("deser post hook!"); + propertyMap = new HashMap(); + + Iterator propertyIter = properties.iterator(); + + while (propertyIter.hasNext()) + { + KeyProperty key = (KeyProperty) propertyIter.next(); + Property value = propertyIter.next(); + + String temp = key.getContents(); + + propertyMap.put(key.getContents(), value); + } + + debug("done desr"); + } + + public Property getProperty(String key) + { + return this.propertyMap.get(key); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/FalseProperty.java b/simplCore/src/ecologylab/serialization/library/apple/FalseProperty.java index 0c906ad6..0c0c7a26 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/FalseProperty.java +++ b/simplCore/src/ecologylab/serialization/library/apple/FalseProperty.java @@ -1,25 +1,25 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_inherit -@simpl_tag("false") -public class FalseProperty extends BooleanProperty -{ - - /** - * - */ - public FalseProperty() - { - this.contents = false; - } - -} +/** + * + */ +package ecologylab.serialization.library.apple; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_inherit +@simpl_tag("false") +public class FalseProperty extends BooleanProperty +{ + + /** + * + */ + public FalseProperty() + { + this.contents = false; + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/IntegerProperty.java b/simplCore/src/ecologylab/serialization/library/apple/IntegerProperty.java index ac97b735..56cd22cb 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/IntegerProperty.java +++ b/simplCore/src/ecologylab/serialization/library/apple/IntegerProperty.java @@ -1,37 +1,37 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_tag("integer") -@simpl_inherit -public class IntegerProperty extends Property -{ - @simpl_hints( - { Hint.XML_TEXT }) - @simpl_scalar - int contents; - - /** - * - */ - public IntegerProperty() - { - // TODO Auto-generated constructor stub - } - - @Override - public String toString() - { - return "IntegerProperty: "+contents; - } -} +/** + * + */ +package ecologylab.serialization.library.apple; + +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_tag("integer") +@simpl_inherit +public class IntegerProperty extends Property +{ + @simpl_hints( + { Hint.XML_TEXT }) + @simpl_scalar + int contents; + + /** + * + */ + public IntegerProperty() + { + // TODO Auto-generated constructor stub + } + + @Override + public String toString() + { + return "IntegerProperty: "+contents; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/KeyProperty.java b/simplCore/src/ecologylab/serialization/library/apple/KeyProperty.java index 1db0b71f..aa10c398 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/KeyProperty.java +++ b/simplCore/src/ecologylab/serialization/library/apple/KeyProperty.java @@ -1,56 +1,56 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -import java.io.File; - -import ecologylab.generic.Debug; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_tag("key") -@simpl_inherit -public class KeyProperty extends StringProperty -{ - - /** - * - */ - public KeyProperty() - { - } - - public KeyProperty(String string) - { - this.contents = string; - } - - @Override - public String toString() - { - return "KeyProperty: " + contents; - } - - public static void main(String[] args) throws SIMPLTranslationException - { - SimplTypesScope key = PListTranslations.getKey(); - StringProperty sample = (StringProperty) key.deserialize( new File("/Users/toupsz/Documents/workspace/ecologylabFundamental/ecologylab/serialization/library/apple/keyTest.xml"), - Format.XML); - - Debug.println("sample: " + sample.toString()); - - KeyProperty newKey = new KeyProperty("hi"); - Debug.println("newKey: " + SimplTypesScope.serialize(newKey, StringFormat.XML)); - - StringProperty newString = new StringProperty("hi"); - Debug.println("newString: " + SimplTypesScope.serialize(newString, StringFormat.XML)); - } -} +/** + * + */ +package ecologylab.serialization.library.apple; + +import java.io.File; + +import ecologylab.generic.Debug; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_tag("key") +@simpl_inherit +public class KeyProperty extends StringProperty +{ + + /** + * + */ + public KeyProperty() + { + } + + public KeyProperty(String string) + { + this.contents = string; + } + + @Override + public String toString() + { + return "KeyProperty: " + contents; + } + + public static void main(String[] args) throws SIMPLTranslationException + { + SimplTypesScope key = PListTranslations.getKey(); + StringProperty sample = (StringProperty) key.deserialize( new File("/Users/toupsz/Documents/workspace/ecologylabFundamental/ecologylab/serialization/library/apple/keyTest.xml"), + Format.XML); + + Debug.println("sample: " + sample.toString()); + + KeyProperty newKey = new KeyProperty("hi"); + Debug.println("newKey: " + SimplTypesScope.serialize(newKey, StringFormat.XML)); + + StringProperty newString = new StringProperty("hi"); + Debug.println("newString: " + SimplTypesScope.serialize(newString, StringFormat.XML)); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/PList.java b/simplCore/src/ecologylab/serialization/library/apple/PList.java index 9e43cbef..e75b6acf 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/PList.java +++ b/simplCore/src/ecologylab/serialization/library/apple/PList.java @@ -1,54 +1,54 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -import java.io.File; - -import ecologylab.generic.Debug; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.formatenums.Format; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_tag("plist") -public class PList extends ElementState -{ - @simpl_scalar - double version; - - @simpl_composite - DictionaryProperty dict; - - public PList() - { - - } - - public DictionaryProperty getDict() - { - return dict; - } - - public static void main(String[] args) throws SIMPLTranslationException - { - PList sample = (PList) PListTranslations.get() - .deserialize( new File("/Users/toupsz/Documents/workspace/ecologylabFundamental/ecologylab/serialization/library/apple/plist.xml"), - Format.XML); - - for (Property p : sample.getDict().propertyMap.values()) - { - Debug.println(p.toString()); - } - - for (Property p : sample.getDict().properties) - { - Debug.println(p.toString()); - } - } -} +/** + * + */ +package ecologylab.serialization.library.apple; + +import java.io.File; + +import ecologylab.generic.Debug; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.formatenums.Format; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_tag("plist") +public class PList extends ElementState +{ + @simpl_scalar + double version; + + @simpl_composite + DictionaryProperty dict; + + public PList() + { + + } + + public DictionaryProperty getDict() + { + return dict; + } + + public static void main(String[] args) throws SIMPLTranslationException + { + PList sample = (PList) PListTranslations.get() + .deserialize( new File("/Users/toupsz/Documents/workspace/ecologylabFundamental/ecologylab/serialization/library/apple/plist.xml"), + Format.XML); + + for (Property p : sample.getDict().propertyMap.values()) + { + Debug.println(p.toString()); + } + + for (Property p : sample.getDict().properties) + { + Debug.println(p.toString()); + } + } +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/PListTranslations.java b/simplCore/src/ecologylab/serialization/library/apple/PListTranslations.java index 0e11a26f..232440f7 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/PListTranslations.java +++ b/simplCore/src/ecologylab/serialization/library/apple/PListTranslations.java @@ -1,58 +1,58 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -import java.io.File; -import java.io.IOException; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class PListTranslations -{ - public static final String NAME = "Apple PList"; - - protected static final Class TRANSLATIONS[] = - { - ecologylab.serialization.library.apple.DictionaryProperty.class, KeyProperty.class, - PList.class, Property.class, StringProperty.class, ArrayProperty.class, - IntegerProperty.class, ArrayProperty.class, BooleanProperty.class, TrueProperty.class, - FalseProperty.class, RealProperty.class, DataProperty.class }; - - public static SimplTypesScope get() - { - return SimplTypesScope.get(NAME, TRANSLATIONS); - } - - public static void main(String[] args) throws SIMPLTranslationException, IOException - { - PList result = (PList) PListTranslations.get() - // .deserialize("/Users/toupsz/Dropbox/ttecBibForBill/simpTest2.xml"); - .deserialize( new File("ecologylab/serialization/library/apple/plist.xml"), - Format.XML); - - - SimplTypesScope.serialize(result, System.out, StringFormat.XML); -// ClassDescriptor.serialize(result, -// new File("/Users/toupsz/Dropbox/ttecBibForBill/tecNewTutMap2.xml"), -// Format.XML); - } - - public static final String KEY_NAME = "KeyTrans"; - - protected static final Class KEY_TRANSLATIONS[] = - { - KeyProperty.class, - Property.class, StringProperty.class }; - - public static SimplTypesScope getKey() - { - return SimplTypesScope.get(KEY_NAME, KEY_TRANSLATIONS); - } -} +/** + * + */ +package ecologylab.serialization.library.apple; + +import java.io.File; +import java.io.IOException; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class PListTranslations +{ + public static final String NAME = "Apple PList"; + + protected static final Class TRANSLATIONS[] = + { + ecologylab.serialization.library.apple.DictionaryProperty.class, KeyProperty.class, + PList.class, Property.class, StringProperty.class, ArrayProperty.class, + IntegerProperty.class, ArrayProperty.class, BooleanProperty.class, TrueProperty.class, + FalseProperty.class, RealProperty.class, DataProperty.class }; + + public static SimplTypesScope get() + { + return SimplTypesScope.get(NAME, TRANSLATIONS); + } + + public static void main(String[] args) throws SIMPLTranslationException, IOException + { + PList result = (PList) PListTranslations.get() + // .deserialize("/Users/toupsz/Dropbox/ttecBibForBill/simpTest2.xml"); + .deserialize( new File("ecologylab/serialization/library/apple/plist.xml"), + Format.XML); + + + SimplTypesScope.serialize(result, System.out, StringFormat.XML); +// ClassDescriptor.serialize(result, +// new File("/Users/toupsz/Dropbox/ttecBibForBill/tecNewTutMap2.xml"), +// Format.XML); + } + + public static final String KEY_NAME = "KeyTrans"; + + protected static final Class KEY_TRANSLATIONS[] = + { + KeyProperty.class, + Property.class, StringProperty.class }; + + public static SimplTypesScope getKey() + { + return SimplTypesScope.get(KEY_NAME, KEY_TRANSLATIONS); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/Property.java b/simplCore/src/ecologylab/serialization/library/apple/Property.java index 8f8663e0..1d31dbed 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/Property.java +++ b/simplCore/src/ecologylab/serialization/library/apple/Property.java @@ -1,24 +1,24 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * A generic property in an Apple P(roperty) List. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_inherit -public class Property extends ElementState -{ - /** - * - */ - public Property() - { - // TODO Auto-generated constructor stub - } -} +/** + * + */ +package ecologylab.serialization.library.apple; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * A generic property in an Apple P(roperty) List. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_inherit +public class Property extends ElementState +{ + /** + * + */ + public Property() + { + // TODO Auto-generated constructor stub + } +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/RealProperty.java b/simplCore/src/ecologylab/serialization/library/apple/RealProperty.java index 2895ca83..b659d4f3 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/RealProperty.java +++ b/simplCore/src/ecologylab/serialization/library/apple/RealProperty.java @@ -1,37 +1,37 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_tag("real") -@simpl_inherit -public class RealProperty extends Property -{ - @simpl_hints( - { Hint.XML_TEXT }) - @simpl_scalar - double contents; - - /** - * - */ - public RealProperty() - { - // TODO Auto-generated constructor stub - } - - public double getContents() - { - return this.contents; - } - -} +/** + * + */ +package ecologylab.serialization.library.apple; + +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_tag("real") +@simpl_inherit +public class RealProperty extends Property +{ + @simpl_hints( + { Hint.XML_TEXT }) + @simpl_scalar + double contents; + + /** + * + */ + public RealProperty() + { + // TODO Auto-generated constructor stub + } + + public double getContents() + { + return this.contents; + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/StringProperty.java b/simplCore/src/ecologylab/serialization/library/apple/StringProperty.java index 92ee2f4b..9614b4b6 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/StringProperty.java +++ b/simplCore/src/ecologylab/serialization/library/apple/StringProperty.java @@ -1,46 +1,46 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_tag("string") -@simpl_inherit -public class StringProperty extends Property -{ - @simpl_hints( - { Hint.XML_TEXT }) - @simpl_scalar - String contents; - - /** - * - */ - public StringProperty() - { - } - - public StringProperty(String string) - { - this.contents = string; - } - - public String getContents() - { - return contents; - } - - @Override - public String toString() - { - return "StringProperty: " + contents; - } -} +/** + * + */ +package ecologylab.serialization.library.apple; + +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_tag("string") +@simpl_inherit +public class StringProperty extends Property +{ + @simpl_hints( + { Hint.XML_TEXT }) + @simpl_scalar + String contents; + + /** + * + */ + public StringProperty() + { + } + + public StringProperty(String string) + { + this.contents = string; + } + + public String getContents() + { + return contents; + } + + @Override + public String toString() + { + return "StringProperty: " + contents; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/TrueProperty.java b/simplCore/src/ecologylab/serialization/library/apple/TrueProperty.java index 7872d719..db32f4df 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/TrueProperty.java +++ b/simplCore/src/ecologylab/serialization/library/apple/TrueProperty.java @@ -1,25 +1,25 @@ -/** - * - */ -package ecologylab.serialization.library.apple; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_inherit -@simpl_tag("true") -public class TrueProperty extends BooleanProperty -{ - - /** - * - */ - public TrueProperty() - { - this.contents = true; - } - -} +/** + * + */ +package ecologylab.serialization.library.apple; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_inherit +@simpl_tag("true") +public class TrueProperty extends BooleanProperty +{ + + /** + * + */ + public TrueProperty() + { + this.contents = true; + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/apple/plist.xml b/simplCore/src/ecologylab/serialization/library/apple/plist.xml index 9056147f..dfebd044 100644 --- a/simplCore/src/ecologylab/serialization/library/apple/plist.xml +++ b/simplCore/src/ecologylab/serialization/library/apple/plist.xml @@ -1,18 +1,18 @@ - - - - - Year Of Birth - 1965 - Photo - PEKBpYGlmYFCPAfekjf39495265Afgfg0052fj81DG== - Hobby - Swimming - Jobs - - Software engineer - Salesperson - - + + + + + Year Of Birth + 1965 + Photo + PEKBpYGlmYFCPAfekjf39495265Afgfg0052fj81DG== + Hobby + Swimming + Jobs + + Software engineer + Salesperson + + \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/library/bibtex/Entry.java b/simplCore/src/ecologylab/serialization/library/bibtex/Entry.java index 1b34eebd..0c557ec8 100644 --- a/simplCore/src/ecologylab/serialization/library/bibtex/Entry.java +++ b/simplCore/src/ecologylab/serialization/library/bibtex/Entry.java @@ -1,311 +1,311 @@ -package ecologylab.serialization.library.bibtex; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.bibtex_key; -import ecologylab.serialization.annotations.bibtex_tag; -import ecologylab.serialization.annotations.bibtex_type; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.StringFormat; - -@bibtex_type("article") -public class Entry extends ElementState -{ - @bibtex_key - @simpl_scalar - private String citationKey; - - @bibtex_tag("title") - @simpl_scalar - private String title; - - @bibtex_tag("authors") - @simpl_nowrap - @simpl_collection("author") - private ArrayList authors; - - @bibtex_tag("journals") - @simpl_scalar - private String journal; - - @bibtex_tag("volume") - @simpl_scalar - private Integer volume; - - @bibtex_tag("issue") - @simpl_scalar - private Integer issue; - - @bibtex_tag("month") - @simpl_scalar - private String month; - - @bibtex_tag("year") - @simpl_scalar - private String year; - - @bibtex_tag("issn") - @simpl_scalar - private String issn; - - @bibtex_tag("pages") - @simpl_scalar - private String pages; - - @bibtex_tag("numPages") - @simpl_scalar - private String numPages; - - @bibtex_tag("url") - @simpl_scalar - private ParsedURL url; - - @bibtex_tag("acmid") - @simpl_scalar - private String acmid; - - @bibtex_tag("publisher") - @simpl_scalar - private String publisher; - - @bibtex_tag("address") - @simpl_scalar - private String address; - - @bibtex_tag("keywords") - @simpl_collection("keywords") - private ArrayList keywords; - - public Entry() - { - - } - - public void setTitle(String title) - { - this.title = title; - } - - public String getTitle() - { - return title; - } - - public void setAuthors(ArrayList authors) - { - this.authors = authors; - } - - public ArrayList getAuthors() - { - return authors; - } - - public void setJournal(String journal) - { - this.journal = journal; - } - - public String getJournal() - { - return journal; - } - - public void setVolume(Integer volume) - { - this.volume = volume; - } - - public Integer getVolume() - { - return volume; - } - - public void setIssue(Integer issue) - { - this.issue = issue; - } - - public Integer getIssue() - { - return issue; - } - - public void setMonth(String month) - { - this.month = month; - } - - public String getMonth() - { - return month; - } - - public void setYear(String year) - { - this.year = year; - } - - public String getYear() - { - return year; - } - - public void setPages(String pages) - { - this.pages = pages; - } - - public String getPages() - { - return pages; - } - - public void setNumPages(String numPages) - { - this.numPages = numPages; - } - - public String getNumPages() - { - return numPages; - } - - public void setUrl(ParsedURL url) - { - this.url = url; - } - - public ParsedURL getUrl() - { - return url; - } - - public void setAcmid(String acmid) - { - this.acmid = acmid; - } - - public String getAcmid() - { - return acmid; - } - - public void setPublisher(String publisher) - { - this.publisher = publisher; - } - - public String getPublisher() - { - return publisher; - } - - public void setAddress(String address) - { - this.address = address; - } - - public String getAddress() - { - return address; - } - - public void setKeywords(ArrayList keywords) - { - this.keywords = keywords; - } - - public ArrayList getKeywords() - { - return keywords; - } - - public void setIssn(String issn) - { - this.issn = issn; - } - - public String getIssn() - { - return issn; - } - - public void setCitationKey(String citationKey) - { - this.citationKey = citationKey; - } - - public String getCitationKey() - { - return citationKey; - } - - public static void main(String args[]) throws SIMPLTranslationException, MalformedURLException - { - /* - @article{Yu:1995:ECK:627296.627650, - author = {Yu, Sheng-Ke}, - title = {Errata: Comments on 'Knowledge Representation Using Fuzzy Petri Nets'}, - journal = {IEEE Trans. on Knowl. and Data Eng.}, - volume = {7}, - issue = {1}, - month = {February}, - year = {1995}, - issn = {1041-4347}, - pages = {190--192}, - numpages = {3}, - url = {http://portal.acm.org/citation.cfm?id=627296.627650}, - acmid = {627650}, - publisher = {IEEE Educational Activities Department}, - address = {Piscataway, NJ, USA}, - keywords = {Fuzzy Petri Net, fuzzy production rule, fuzzy reasoning, immediate reachability set, knowledge representation, reachability set.}, - } - */ - - Entry e = new Entry(); - - ArrayList authors = new ArrayList(); - ArrayList keywords = new ArrayList(); - - authors.add("Yu"); - authors.add("Sheng-Ke"); - - keywords.add("Fuzzy Petri Nets"); - keywords.add("fuzzy production rule"); - keywords.add("fuzzy reasoning"); - keywords.add("immediate reachability set"); - keywords.add("knowledge representation"); - keywords.add("reachability set"); - - e.setCitationKey("Yu:1995:ECK:627296.627650"); - e.setAuthors(authors); - e.setTitle("Errata: Comments on Knowledge Representation Using Fuzzy Petri Nets"); - e.setJournal("IEEE Trans. on Knowl. and Data Eng."); - e.setVolume(1); - e.setIssue(1); - e.setMonth("Feburary"); - e.setYear("1995"); - e.setIssn("1041-4347"); - e.setPages("190--192"); - e.setNumPages("3"); - e.setUrl(new ParsedURL(new URL("http://portal.acm.org/citation.cfm?id=627296.627650"))); - e.setAcmid("627650"); - e.setPublisher("IEEE Educational Activities Department"); - e.setAddress("Piscataway, NJ, USA"); - e.setKeywords(keywords); - - SimplTypesScope.serialize(e, System.out, StringFormat.BIBTEX); - } - - - -} +package ecologylab.serialization.library.bibtex; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.bibtex_key; +import ecologylab.serialization.annotations.bibtex_tag; +import ecologylab.serialization.annotations.bibtex_type; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.StringFormat; + +@bibtex_type("article") +public class Entry extends ElementState +{ + @bibtex_key + @simpl_scalar + private String citationKey; + + @bibtex_tag("title") + @simpl_scalar + private String title; + + @bibtex_tag("authors") + @simpl_nowrap + @simpl_collection("author") + private ArrayList authors; + + @bibtex_tag("journals") + @simpl_scalar + private String journal; + + @bibtex_tag("volume") + @simpl_scalar + private Integer volume; + + @bibtex_tag("issue") + @simpl_scalar + private Integer issue; + + @bibtex_tag("month") + @simpl_scalar + private String month; + + @bibtex_tag("year") + @simpl_scalar + private String year; + + @bibtex_tag("issn") + @simpl_scalar + private String issn; + + @bibtex_tag("pages") + @simpl_scalar + private String pages; + + @bibtex_tag("numPages") + @simpl_scalar + private String numPages; + + @bibtex_tag("url") + @simpl_scalar + private ParsedURL url; + + @bibtex_tag("acmid") + @simpl_scalar + private String acmid; + + @bibtex_tag("publisher") + @simpl_scalar + private String publisher; + + @bibtex_tag("address") + @simpl_scalar + private String address; + + @bibtex_tag("keywords") + @simpl_collection("keywords") + private ArrayList keywords; + + public Entry() + { + + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getTitle() + { + return title; + } + + public void setAuthors(ArrayList authors) + { + this.authors = authors; + } + + public ArrayList getAuthors() + { + return authors; + } + + public void setJournal(String journal) + { + this.journal = journal; + } + + public String getJournal() + { + return journal; + } + + public void setVolume(Integer volume) + { + this.volume = volume; + } + + public Integer getVolume() + { + return volume; + } + + public void setIssue(Integer issue) + { + this.issue = issue; + } + + public Integer getIssue() + { + return issue; + } + + public void setMonth(String month) + { + this.month = month; + } + + public String getMonth() + { + return month; + } + + public void setYear(String year) + { + this.year = year; + } + + public String getYear() + { + return year; + } + + public void setPages(String pages) + { + this.pages = pages; + } + + public String getPages() + { + return pages; + } + + public void setNumPages(String numPages) + { + this.numPages = numPages; + } + + public String getNumPages() + { + return numPages; + } + + public void setUrl(ParsedURL url) + { + this.url = url; + } + + public ParsedURL getUrl() + { + return url; + } + + public void setAcmid(String acmid) + { + this.acmid = acmid; + } + + public String getAcmid() + { + return acmid; + } + + public void setPublisher(String publisher) + { + this.publisher = publisher; + } + + public String getPublisher() + { + return publisher; + } + + public void setAddress(String address) + { + this.address = address; + } + + public String getAddress() + { + return address; + } + + public void setKeywords(ArrayList keywords) + { + this.keywords = keywords; + } + + public ArrayList getKeywords() + { + return keywords; + } + + public void setIssn(String issn) + { + this.issn = issn; + } + + public String getIssn() + { + return issn; + } + + public void setCitationKey(String citationKey) + { + this.citationKey = citationKey; + } + + public String getCitationKey() + { + return citationKey; + } + + public static void main(String args[]) throws SIMPLTranslationException, MalformedURLException + { + /* + @article{Yu:1995:ECK:627296.627650, + author = {Yu, Sheng-Ke}, + title = {Errata: Comments on 'Knowledge Representation Using Fuzzy Petri Nets'}, + journal = {IEEE Trans. on Knowl. and Data Eng.}, + volume = {7}, + issue = {1}, + month = {February}, + year = {1995}, + issn = {1041-4347}, + pages = {190--192}, + numpages = {3}, + url = {http://portal.acm.org/citation.cfm?id=627296.627650}, + acmid = {627650}, + publisher = {IEEE Educational Activities Department}, + address = {Piscataway, NJ, USA}, + keywords = {Fuzzy Petri Net, fuzzy production rule, fuzzy reasoning, immediate reachability set, knowledge representation, reachability set.}, + } + */ + + Entry e = new Entry(); + + ArrayList authors = new ArrayList(); + ArrayList keywords = new ArrayList(); + + authors.add("Yu"); + authors.add("Sheng-Ke"); + + keywords.add("Fuzzy Petri Nets"); + keywords.add("fuzzy production rule"); + keywords.add("fuzzy reasoning"); + keywords.add("immediate reachability set"); + keywords.add("knowledge representation"); + keywords.add("reachability set"); + + e.setCitationKey("Yu:1995:ECK:627296.627650"); + e.setAuthors(authors); + e.setTitle("Errata: Comments on Knowledge Representation Using Fuzzy Petri Nets"); + e.setJournal("IEEE Trans. on Knowl. and Data Eng."); + e.setVolume(1); + e.setIssue(1); + e.setMonth("Feburary"); + e.setYear("1995"); + e.setIssn("1041-4347"); + e.setPages("190--192"); + e.setNumPages("3"); + e.setUrl(new ParsedURL(new URL("http://portal.acm.org/citation.cfm?id=627296.627650"))); + e.setAcmid("627650"); + e.setPublisher("IEEE Educational Activities Department"); + e.setAddress("Piscataway, NJ, USA"); + e.setKeywords(keywords); + + SimplTypesScope.serialize(e, System.out, StringFormat.BIBTEX); + } + + + +} diff --git a/simplCore/src/ecologylab/serialization/library/dc/Dc.java b/simplCore/src/ecologylab/serialization/library/dc/Dc.java index 3c8a1b5f..6d29c5e3 100644 --- a/simplCore/src/ecologylab/serialization/library/dc/Dc.java +++ b/simplCore/src/ecologylab/serialization/library/dc/Dc.java @@ -1,195 +1,195 @@ -package ecologylab.serialization.library.dc; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Dublin Core Metadata Element Set, as defined at - * - * - * - * There is no enclosing parent element in the XML markup. - * - * @author andruid - */ -public class Dc extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String creator; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String subject; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String publisher; - // Contributor - // public Date date; // we need to implement a better Date type! - // values for type: Collection, Dataset, Event, Image, MovingImage, - // InteractiveResource, PhysicalObject, Service, Software, Sound, - // StillImage, Text - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String type; - /** - * Probably the mime-type, but alas not necessarily. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String format; - /** - * Recommended best practice is to identify the resource by means of a string or number conforming to a formal identification system. Formal identification systems include but are not limited to the Uniform Resource Identifier (URI) (including the Uniform Resource Locator (URL)), the Digital Object Identifier (DOI) and the International Standard Book Number (ISBN). - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL identifier; - // language - // relation - // coverage - // rights - - // from http://memory.loc.gov/ammem/award/docs/dublin-examples.html#thirteen - - // public String author; - // public String otherAgent - // public String otherType; - // public String form; // instead of format - - private static final String TRANSLATION_SPACE_NAME = "dc"; - private static final String PACKAGE_NAME = "ecologylab.serialization.library.dc"; - - public static final Class TRANSLATIONS[] = - { - Dc.class, - }; - - public static SimplTypesScope get() - { - return SimplTypesScope.get(TRANSLATION_SPACE_NAME, TRANSLATIONS); - } - - public Dc() {} - - /** - * @return Returns the creator. - */ - public String getCreator() - { - return creator; - } - - /** - * @param creator The creator to set. - */ - public void setCreator(String creator) - { - this.creator = creator; - } - - /** - * @return Returns the description. - */ - public String getDescription() - { - return description; - } - - /** - * @param description The description to set. - */ - public void setDescription(String description) - { - this.description = description; - } - - /** - * @return Returns the format. - */ - public String getFormat() - { - return format; - } - - /** - * @param format The format to set. - */ - public void setFormat(String format) - { - this.format = format; - } - - /** - * @return Returns the identifier. - */ - public ParsedURL getIdentifier() - { - return identifier; - } - - /** - * @param identifier The identifier to set. - */ - public void setIdentifier(ParsedURL identifier) - { - this.identifier = identifier; - } - - /** - * @return Returns the publisher. - */ - public String getPublisher() - { - return publisher; - } - - /** - * @param publisher The publisher to set. - */ - public void setPublisher(String publisher) - { - this.publisher = publisher; - } - - /** - * @return Returns the subject. - */ - public String getSubject() - { - return subject; - } - - /** - * @param subject The subject to set. - */ - public void setSubject(String subject) - { - this.subject = subject; - } - - /** - * @return Returns the title. - */ - public String getTitle() - { - return title; - } - - /** - * @param title The title to set. - */ - public void setTitle(String title) - { - this.title = title; - } - - - @Override - public String toString() - { - return "Dc {\n" + - "creator: " + creator + "\n" + - "description: " + description + "\n" + - "format: " + format + "\n" + - "identifier: " + identifier + "\n" + - "publisher: " + publisher + "\n" + - "subject: " + subject + "\n" + - "title: " + title + "\n" + - "type: " + type + "\n" + - "}"; - - } -} +package ecologylab.serialization.library.dc; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Dublin Core Metadata Element Set, as defined at + * + * + * + * There is no enclosing parent element in the XML markup. + * + * @author andruid + */ +public class Dc extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String creator; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String subject; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String publisher; + // Contributor + // public Date date; // we need to implement a better Date type! + // values for type: Collection, Dataset, Event, Image, MovingImage, + // InteractiveResource, PhysicalObject, Service, Software, Sound, + // StillImage, Text + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String type; + /** + * Probably the mime-type, but alas not necessarily. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String format; + /** + * Recommended best practice is to identify the resource by means of a string or number conforming to a formal identification system. Formal identification systems include but are not limited to the Uniform Resource Identifier (URI) (including the Uniform Resource Locator (URL)), the Digital Object Identifier (DOI) and the International Standard Book Number (ISBN). + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL identifier; + // language + // relation + // coverage + // rights + + // from http://memory.loc.gov/ammem/award/docs/dublin-examples.html#thirteen + + // public String author; + // public String otherAgent + // public String otherType; + // public String form; // instead of format + + private static final String TRANSLATION_SPACE_NAME = "dc"; + private static final String PACKAGE_NAME = "ecologylab.serialization.library.dc"; + + public static final Class TRANSLATIONS[] = + { + Dc.class, + }; + + public static SimplTypesScope get() + { + return SimplTypesScope.get(TRANSLATION_SPACE_NAME, TRANSLATIONS); + } + + public Dc() {} + + /** + * @return Returns the creator. + */ + public String getCreator() + { + return creator; + } + + /** + * @param creator The creator to set. + */ + public void setCreator(String creator) + { + this.creator = creator; + } + + /** + * @return Returns the description. + */ + public String getDescription() + { + return description; + } + + /** + * @param description The description to set. + */ + public void setDescription(String description) + { + this.description = description; + } + + /** + * @return Returns the format. + */ + public String getFormat() + { + return format; + } + + /** + * @param format The format to set. + */ + public void setFormat(String format) + { + this.format = format; + } + + /** + * @return Returns the identifier. + */ + public ParsedURL getIdentifier() + { + return identifier; + } + + /** + * @param identifier The identifier to set. + */ + public void setIdentifier(ParsedURL identifier) + { + this.identifier = identifier; + } + + /** + * @return Returns the publisher. + */ + public String getPublisher() + { + return publisher; + } + + /** + * @param publisher The publisher to set. + */ + public void setPublisher(String publisher) + { + this.publisher = publisher; + } + + /** + * @return Returns the subject. + */ + public String getSubject() + { + return subject; + } + + /** + * @param subject The subject to set. + */ + public void setSubject(String subject) + { + this.subject = subject; + } + + /** + * @return Returns the title. + */ + public String getTitle() + { + return title; + } + + /** + * @param title The title to set. + */ + public void setTitle(String title) + { + this.title = title; + } + + + @Override + public String toString() + { + return "Dc {\n" + + "creator: " + creator + "\n" + + "description: " + description + "\n" + + "format: " + format + "\n" + + "identifier: " + identifier + "\n" + + "publisher: " + publisher + "\n" + + "subject: " + subject + "\n" + + "title: " + title + "\n" + + "type: " + type + "\n" + + "}"; + + } +} diff --git a/simplCore/src/ecologylab/serialization/library/dc/DcTag.java b/simplCore/src/ecologylab/serialization/library/dc/DcTag.java index 67ab7643..3643c29c 100644 --- a/simplCore/src/ecologylab/serialization/library/dc/DcTag.java +++ b/simplCore/src/ecologylab/serialization/library/dc/DcTag.java @@ -1,199 +1,199 @@ -package ecologylab.serialization.library.dc; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * Dublin Core Metadata Element Set, as defined at - * - * - * - * There is no enclosing parent element in the XML markup. - * - * @author andruid - */ -public class DcTag extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:title") String title; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:creator") String creator; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:subject") String subject; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:description")String description; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:publisher") String publisher; - // Contributor - // public Date date; // we need to implement a better Date type! - // values for type: Collection, Dataset, Event, Image, MovingImage, - // InteractiveResource, PhysicalObject, Service, Software, Sound, - // StillImage, Text - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:type") String type; - /** - * Probably the mime-type, but alas not necessarily. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:format") String format; - /** - * Recommended best practice is to identify the resource by means of a string or number conforming to a formal identification system. Formal identification systems include but are not limited to the Uniform Resource Identifier (URI) (including the Uniform Resource Locator (URL)), the Digital Object Identifier (DOI) and the International Standard Book Number (ISBN). - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:identifier") ParsedURL identifier; - // language - // relation - // coverage - // rights - - // from http://memory.loc.gov/ammem/award/docs/dublin-examples.html#thirteen - - // public String author; - // public String otherAgent - // public String otherType; - // public String form; // instead of format - - private static final String TRANSLATION_SPACE_NAME = "dc"; - private static final String PACKAGE_NAME = "ecologylab.serialization.library.dc"; - - public static final Class TRANSLATIONS[] = - { - Dc.class, - }; - - public static SimplTypesScope get() - { - return SimplTypesScope.get(TRANSLATION_SPACE_NAME, TRANSLATIONS); - } - - public DcTag() - { - - } - - /** - * @return Returns the creator. - */ - public String getCreator() - { - return creator; - } - - /** - * @param creator The creator to set. - */ - public void setCreator(String creator) - { - this.creator = creator; - } - - /** - * @return Returns the description. - */ - public String getDescription() - { - return description; - } - - /** - * @param description The description to set. - */ - public void setDescription(String description) - { - this.description = description; - } - - /** - * @return Returns the format. - */ - public String getFormat() - { - return format; - } - - /** - * @param format The format to set. - */ - public void setFormat(String format) - { - this.format = format; - } - - /** - * @return Returns the identifier. - */ - public ParsedURL getIdentifier() - { - return identifier; - } - - /** - * @param identifier The identifier to set. - */ - public void setIdentifier(ParsedURL identifier) - { - this.identifier = identifier; - } - - /** - * @return Returns the publisher. - */ - public String getPublisher() - { - return publisher; - } - - /** - * @param publisher The publisher to set. - */ - public void setPublisher(String publisher) - { - this.publisher = publisher; - } - - /** - * @return Returns the subject. - */ - public String getSubject() - { - return subject; - } - - /** - * @param subject The subject to set. - */ - public void setSubject(String subject) - { - this.subject = subject; - } - - /** - * @return Returns the title. - */ - public String getTitle() - { - return title; - } - - /** - * @param title The title to set. - */ - public void setTitle(String title) - { - this.title = title; - } - - - @Override - public String toString() - { - return "Dc {\n" + - "creator: " + creator + "\n" + - "description: " + description + "\n" + - "format: " + format + "\n" + - "identifier: " + identifier + "\n" + - "publisher: " + publisher + "\n" + - "subject: " + subject + "\n" + - "title: " + title + "\n" + - "type: " + type + "\n" + - "}"; - - } -} +package ecologylab.serialization.library.dc; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * Dublin Core Metadata Element Set, as defined at + * + * + * + * There is no enclosing parent element in the XML markup. + * + * @author andruid + */ +public class DcTag extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:title") String title; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:creator") String creator; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:subject") String subject; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:description")String description; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:publisher") String publisher; + // Contributor + // public Date date; // we need to implement a better Date type! + // values for type: Collection, Dataset, Event, Image, MovingImage, + // InteractiveResource, PhysicalObject, Service, Software, Sound, + // StillImage, Text + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:type") String type; + /** + * Probably the mime-type, but alas not necessarily. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:format") String format; + /** + * Recommended best practice is to identify the resource by means of a string or number conforming to a formal identification system. Formal identification systems include but are not limited to the Uniform Resource Identifier (URI) (including the Uniform Resource Locator (URL)), the Digital Object Identifier (DOI) and the International Standard Book Number (ISBN). + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("dc:identifier") ParsedURL identifier; + // language + // relation + // coverage + // rights + + // from http://memory.loc.gov/ammem/award/docs/dublin-examples.html#thirteen + + // public String author; + // public String otherAgent + // public String otherType; + // public String form; // instead of format + + private static final String TRANSLATION_SPACE_NAME = "dc"; + private static final String PACKAGE_NAME = "ecologylab.serialization.library.dc"; + + public static final Class TRANSLATIONS[] = + { + Dc.class, + }; + + public static SimplTypesScope get() + { + return SimplTypesScope.get(TRANSLATION_SPACE_NAME, TRANSLATIONS); + } + + public DcTag() + { + + } + + /** + * @return Returns the creator. + */ + public String getCreator() + { + return creator; + } + + /** + * @param creator The creator to set. + */ + public void setCreator(String creator) + { + this.creator = creator; + } + + /** + * @return Returns the description. + */ + public String getDescription() + { + return description; + } + + /** + * @param description The description to set. + */ + public void setDescription(String description) + { + this.description = description; + } + + /** + * @return Returns the format. + */ + public String getFormat() + { + return format; + } + + /** + * @param format The format to set. + */ + public void setFormat(String format) + { + this.format = format; + } + + /** + * @return Returns the identifier. + */ + public ParsedURL getIdentifier() + { + return identifier; + } + + /** + * @param identifier The identifier to set. + */ + public void setIdentifier(ParsedURL identifier) + { + this.identifier = identifier; + } + + /** + * @return Returns the publisher. + */ + public String getPublisher() + { + return publisher; + } + + /** + * @param publisher The publisher to set. + */ + public void setPublisher(String publisher) + { + this.publisher = publisher; + } + + /** + * @return Returns the subject. + */ + public String getSubject() + { + return subject; + } + + /** + * @param subject The subject to set. + */ + public void setSubject(String subject) + { + this.subject = subject; + } + + /** + * @return Returns the title. + */ + public String getTitle() + { + return title; + } + + /** + * @param title The title to set. + */ + public void setTitle(String title) + { + this.title = title; + } + + + @Override + public String toString() + { + return "Dc {\n" + + "creator: " + creator + "\n" + + "description: " + description + "\n" + + "format: " + format + "\n" + + "identifier: " + identifier + "\n" + + "publisher: " + publisher + "\n" + + "subject: " + subject + "\n" + + "title: " + title + "\n" + + "type: " + type + "\n" + + "}"; + + } +} diff --git a/simplCore/src/ecologylab/serialization/library/dc/package.html b/simplCore/src/ecologylab/serialization/library/dc/package.html index 7f036357..ff15af7e 100644 --- a/simplCore/src/ecologylab/serialization/library/dc/package.html +++ b/simplCore/src/ecologylab/serialization/library/dc/package.html @@ -1,5 +1,5 @@ - -{@link ecologylab.xml.ElementState ElementState} - subclasses that enable translation of XML entities from the -Dublin-Core namespace. - + +{@link ecologylab.xml.ElementState ElementState} + subclasses that enable translation of XML entities from the +Dublin-Core namespace. + diff --git a/simplCore/src/ecologylab/serialization/library/endnote/Author.java b/simplCore/src/ecologylab/serialization/library/endnote/Author.java index 8821ddf0..7d3d6020 100644 --- a/simplCore/src/ecologylab/serialization/library/endnote/Author.java +++ b/simplCore/src/ecologylab/serialization/library/endnote/Author.java @@ -1,30 +1,30 @@ -/* - * Created on Dec 12, 2006 - */ -package ecologylab.serialization.library.endnote; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -public @simpl_inherit -class Author extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_TEXT) - String authorName; - - public Author() - { - - } - - /** - * @return the authorName - */ - public String getAuthorName() - { - return authorName; - } -} +/* + * Created on Dec 12, 2006 + */ +package ecologylab.serialization.library.endnote; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +public @simpl_inherit +class Author extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_TEXT) + String authorName; + + public Author() + { + + } + + /** + * @return the authorName + */ + public String getAuthorName() + { + return authorName; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/endnote/ContributorList.java b/simplCore/src/ecologylab/serialization/library/endnote/ContributorList.java index 1556f96e..0178fa34 100644 --- a/simplCore/src/ecologylab/serialization/library/endnote/ContributorList.java +++ b/simplCore/src/ecologylab/serialization/library/endnote/ContributorList.java @@ -1,76 +1,76 @@ -/* - * Created on Dec 12, 2006 - */ -package ecologylab.serialization.library.endnote; - -import java.util.ArrayList; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_nowrap; -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public class ContributorList extends ElementState -{ - @simpl_collection("Author") - @simpl_nowrap - ArrayList authors = new ArrayList(); - -// private @xml_nested ArrayListState secondary-authors = new ArrayListState(); - // private @xml_nested ArrayListState tertiary-authors = new ArrayListState(); - - /** - * - */ - public ContributorList() - { - // TODO Auto-generated constructor stub - } - - /** - * @return the authors - */ - public ArrayList getAuthors() - { - return authors; - } - - public boolean contains(String value) - { - for (Author a : authors) - { - //FIXME -- need to code a newer version of s.im.pl serialization -// if (a.getTextNodeString().toLowerCase().contains(value)) -// { -// return true; -// } - } - return false; - } - - /** - * @return Concatenation of authors. - */ - public String getAuthorListString() - { - StringBuilder string = new StringBuilder(); - - int i = authors.size(); - - for (Author a : authors) - { - //FIXME -- need to code a newer version of s.im.pl serialization -// i--; -// string.append(a.getTextNodeString()); -// -// if (i != 0) -// { -// string.append("; "); -// } - } - - return string.toString(); - } - -} +/* + * Created on Dec 12, 2006 + */ +package ecologylab.serialization.library.endnote; + +import java.util.ArrayList; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_nowrap; +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public class ContributorList extends ElementState +{ + @simpl_collection("Author") + @simpl_nowrap + ArrayList authors = new ArrayList(); + +// private @xml_nested ArrayListState secondary-authors = new ArrayListState(); + // private @xml_nested ArrayListState tertiary-authors = new ArrayListState(); + + /** + * + */ + public ContributorList() + { + // TODO Auto-generated constructor stub + } + + /** + * @return the authors + */ + public ArrayList getAuthors() + { + return authors; + } + + public boolean contains(String value) + { + for (Author a : authors) + { + //FIXME -- need to code a newer version of s.im.pl serialization +// if (a.getTextNodeString().toLowerCase().contains(value)) +// { +// return true; +// } + } + return false; + } + + /** + * @return Concatenation of authors. + */ + public String getAuthorListString() + { + StringBuilder string = new StringBuilder(); + + int i = authors.size(); + + for (Author a : authors) + { + //FIXME -- need to code a newer version of s.im.pl serialization +// i--; +// string.append(a.getTextNodeString()); +// +// if (i != 0) +// { +// string.append("; "); +// } + } + + return string.toString(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/endnote/DateList.java b/simplCore/src/ecologylab/serialization/library/endnote/DateList.java index edbbb650..f4aae830 100644 --- a/simplCore/src/ecologylab/serialization/library/endnote/DateList.java +++ b/simplCore/src/ecologylab/serialization/library/endnote/DateList.java @@ -1,26 +1,26 @@ -/* - * Created on Dec 12, 2006 - */ -package ecologylab.serialization.library.endnote; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.types.element.StringState; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public class DateList extends ElementState -{ - private @simpl_composite StringState year; - -// private @xml_nested String pub-dates = ""; - - /** - * - */ - public DateList() - { - // TODO Auto-generated constructor stub - } -} +/* + * Created on Dec 12, 2006 + */ +package ecologylab.serialization.library.endnote; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.types.element.StringState; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public class DateList extends ElementState +{ + private @simpl_composite StringState year; + +// private @xml_nested String pub-dates = ""; + + /** + * + */ + public DateList() + { + // TODO Auto-generated constructor stub + } +} diff --git a/simplCore/src/ecologylab/serialization/library/endnote/EndnoteNameSpace.java b/simplCore/src/ecologylab/serialization/library/endnote/EndnoteNameSpace.java index 112c9fd7..4e530a12 100755 --- a/simplCore/src/ecologylab/serialization/library/endnote/EndnoteNameSpace.java +++ b/simplCore/src/ecologylab/serialization/library/endnote/EndnoteNameSpace.java @@ -1,51 +1,51 @@ -package ecologylab.serialization.library.endnote; - -import ecologylab.serialization.SimplTypesScope; - -/** - * Contains all of the information necessary to translate XML objects used in - * the network communications of the Rogue game. Use MasterNameSpace.get() to - * acquire a NameSpace object fit for use in the game. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class EndnoteNameSpace -{ - - public static final String NAME = "endnote"; - - protected static final String PACKAGE_NAME = "ecologylab.serialization.library.endnote"; - - protected static final Class TRANSLATIONS[] = - { - - ecologylab.serialization.types.element.StringState.class, ecologylab.serialization.types.element.IntState.class, - ecologylab.serialization.library.endnote.Author.class, - ecologylab.serialization.library.endnote.ContributorList.class, - ecologylab.serialization.library.endnote.DateList.class, - ecologylab.serialization.library.endnote.Keyword.class, - ecologylab.serialization.library.endnote.KeywordList.class, - ecologylab.serialization.library.endnote.Record.class, - ecologylab.serialization.library.endnote.Records.class, - ecologylab.serialization.library.endnote.TitleList.class, - ecologylab.serialization.library.endnote.XmlState.class, - - ecologylab.serialization.library.geom.Point2DDoubleState.class, - ecologylab.serialization.library.geom.Rectangle2DDoubleState.class, - ecologylab.serialization.library.geom.Ellipse2DDoubleState.class, - ecologylab.serialization.library.geom.RectangularShape.class }; - - public static SimplTypesScope get() - { - return SimplTypesScope.get(NAME, TRANSLATIONS); - } - - /** - * @return the tRANSLATIONS - */ - public static Class[] getTRANSLATIONS() - { - return TRANSLATIONS; - } -} +package ecologylab.serialization.library.endnote; + +import ecologylab.serialization.SimplTypesScope; + +/** + * Contains all of the information necessary to translate XML objects used in + * the network communications of the Rogue game. Use MasterNameSpace.get() to + * acquire a NameSpace object fit for use in the game. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class EndnoteNameSpace +{ + + public static final String NAME = "endnote"; + + protected static final String PACKAGE_NAME = "ecologylab.serialization.library.endnote"; + + protected static final Class TRANSLATIONS[] = + { + + ecologylab.serialization.types.element.StringState.class, ecologylab.serialization.types.element.IntState.class, + ecologylab.serialization.library.endnote.Author.class, + ecologylab.serialization.library.endnote.ContributorList.class, + ecologylab.serialization.library.endnote.DateList.class, + ecologylab.serialization.library.endnote.Keyword.class, + ecologylab.serialization.library.endnote.KeywordList.class, + ecologylab.serialization.library.endnote.Record.class, + ecologylab.serialization.library.endnote.Records.class, + ecologylab.serialization.library.endnote.TitleList.class, + ecologylab.serialization.library.endnote.XmlState.class, + + ecologylab.serialization.library.geom.Point2DDoubleState.class, + ecologylab.serialization.library.geom.Rectangle2DDoubleState.class, + ecologylab.serialization.library.geom.Ellipse2DDoubleState.class, + ecologylab.serialization.library.geom.RectangularShape.class }; + + public static SimplTypesScope get() + { + return SimplTypesScope.get(NAME, TRANSLATIONS); + } + + /** + * @return the tRANSLATIONS + */ + public static Class[] getTRANSLATIONS() + { + return TRANSLATIONS; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/endnote/Keyword.java b/simplCore/src/ecologylab/serialization/library/endnote/Keyword.java index 9dc34b4b..c81ef188 100644 --- a/simplCore/src/ecologylab/serialization/library/endnote/Keyword.java +++ b/simplCore/src/ecologylab/serialization/library/endnote/Keyword.java @@ -1,20 +1,20 @@ -/* - * Created on Dec 12, 2006 - */ -package ecologylab.serialization.library.endnote; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public @simpl_inherit class Keyword extends ElementState -{ - /** - * - */ - public Keyword() - { - } -} +/* + * Created on Dec 12, 2006 + */ +package ecologylab.serialization.library.endnote; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public @simpl_inherit class Keyword extends ElementState +{ + /** + * + */ + public Keyword() + { + } +} diff --git a/simplCore/src/ecologylab/serialization/library/endnote/KeywordList.java b/simplCore/src/ecologylab/serialization/library/endnote/KeywordList.java index fb56fb8c..78f4a0e3 100644 --- a/simplCore/src/ecologylab/serialization/library/endnote/KeywordList.java +++ b/simplCore/src/ecologylab/serialization/library/endnote/KeywordList.java @@ -1,67 +1,67 @@ -/* - * Created on Dec 12, 2006 - */ -package ecologylab.serialization.library.endnote; - -import java.util.ArrayList; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_nowrap; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public @simpl_inherit class KeywordList extends ElementState -{ - @simpl_collection("Keyword") - @simpl_nowrap - ArrayList keywords; - - /** - * - */ - public KeywordList() - { - // TODO Auto-generated constructor stub - } - - public boolean containsString(String value) - { - for (Keyword k : keywords) - { - //FIXME -- need to code a newer version of s.im.pl serialization -// if (k.getTextNodeString() != null && k.getTextNodeString().toLowerCase().contains(value)) -// { -// return true; -// } - } - - return false; - } - - /** - * @return list of keywords associated with this. - */ - public String getKeywordListString() - { - StringBuilder string = new StringBuilder(); - - int i = keywords.size(); - - for (Keyword a : keywords) - { - //FIXME -- need to code a newer version of s.im.pl serialization -// i--; -// string.append(a.getTextNodeString()); -// -// if (i != 0) -// { -// string.append("; "); -// } - } - - return string.toString(); - } -} +/* + * Created on Dec 12, 2006 + */ +package ecologylab.serialization.library.endnote; + +import java.util.ArrayList; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_nowrap; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public @simpl_inherit class KeywordList extends ElementState +{ + @simpl_collection("Keyword") + @simpl_nowrap + ArrayList keywords; + + /** + * + */ + public KeywordList() + { + // TODO Auto-generated constructor stub + } + + public boolean containsString(String value) + { + for (Keyword k : keywords) + { + //FIXME -- need to code a newer version of s.im.pl serialization +// if (k.getTextNodeString() != null && k.getTextNodeString().toLowerCase().contains(value)) +// { +// return true; +// } + } + + return false; + } + + /** + * @return list of keywords associated with this. + */ + public String getKeywordListString() + { + StringBuilder string = new StringBuilder(); + + int i = keywords.size(); + + for (Keyword a : keywords) + { + //FIXME -- need to code a newer version of s.im.pl serialization +// i--; +// string.append(a.getTextNodeString()); +// +// if (i != 0) +// { +// string.append("; "); +// } + } + + return string.toString(); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/endnote/Record.java b/simplCore/src/ecologylab/serialization/library/endnote/Record.java index 371b17d5..3df2e8be 100644 --- a/simplCore/src/ecologylab/serialization/library/endnote/Record.java +++ b/simplCore/src/ecologylab/serialization/library/endnote/Record.java @@ -1,132 +1,132 @@ -/* - * Created on Dec 12, 2006 - */ -package ecologylab.serialization.library.endnote; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public class Record extends ElementState -{ - private @simpl_composite ContributorList contributors = new ContributorList(); - -// private @xml_nested int ref-type = 0; - - private @simpl_composite TitleList titles = new TitleList(); - - private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String volume; - - private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String number; - - private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String pages; - -// private @xml_nested String pub-location = ""; - - private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String publisher; - - private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String isbn; - - private @simpl_composite DateList dates = new DateList(); - - private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String label; - - private @simpl_composite KeywordList keywords = new KeywordList(); - -// private @xml_nested URLList urls = new URLList(); - -// private @xml_nested Abstract abstract = new Abstract(); - - /** - * - */ - public Record() - { - } - - /** - * @return the contributors - */ - public ContributorList getContributors() - { - return contributors; - } - - /** - * @return the dates - */ - public DateList getDates() - { - return dates; - } - - /** - * @return the isbn - */ - public String getIsbn() - { - return isbn; - } - - /** - * @return the keywords - */ - public KeywordList getKeywords() - { - return keywords; - } - - /** - * @return the label - */ - public String getLabel() - { - return label; - } - - /** - * @return the number - */ - public String getNumber() - { - return number; - } - - /** - * @return the pages - */ - public String getPages() - { - return pages; - } - - /** - * @return the publisher - */ - public String getPublisher() - { - return publisher; - } - - /** - * @return the titles - */ - public TitleList getTitles() - { - return titles; - } - - /** - * @return the volume - */ - public String getVolume() - { - return volume; - } - -} +/* + * Created on Dec 12, 2006 + */ +package ecologylab.serialization.library.endnote; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public class Record extends ElementState +{ + private @simpl_composite ContributorList contributors = new ContributorList(); + +// private @xml_nested int ref-type = 0; + + private @simpl_composite TitleList titles = new TitleList(); + + private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String volume; + + private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String number; + + private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String pages; + +// private @xml_nested String pub-location = ""; + + private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String publisher; + + private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String isbn; + + private @simpl_composite DateList dates = new DateList(); + + private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String label; + + private @simpl_composite KeywordList keywords = new KeywordList(); + +// private @xml_nested URLList urls = new URLList(); + +// private @xml_nested Abstract abstract = new Abstract(); + + /** + * + */ + public Record() + { + } + + /** + * @return the contributors + */ + public ContributorList getContributors() + { + return contributors; + } + + /** + * @return the dates + */ + public DateList getDates() + { + return dates; + } + + /** + * @return the isbn + */ + public String getIsbn() + { + return isbn; + } + + /** + * @return the keywords + */ + public KeywordList getKeywords() + { + return keywords; + } + + /** + * @return the label + */ + public String getLabel() + { + return label; + } + + /** + * @return the number + */ + public String getNumber() + { + return number; + } + + /** + * @return the pages + */ + public String getPages() + { + return pages; + } + + /** + * @return the publisher + */ + public String getPublisher() + { + return publisher; + } + + /** + * @return the titles + */ + public TitleList getTitles() + { + return titles; + } + + /** + * @return the volume + */ + public String getVolume() + { + return volume; + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/endnote/Records.java b/simplCore/src/ecologylab/serialization/library/endnote/Records.java index cd858403..bb283150 100644 --- a/simplCore/src/ecologylab/serialization/library/endnote/Records.java +++ b/simplCore/src/ecologylab/serialization/library/endnote/Records.java @@ -1,24 +1,24 @@ -/* - * Created on Dec 12, 2006 - */ -package ecologylab.serialization.library.endnote; - -import java.util.ArrayList; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_nowrap; - -public @simpl_inherit class Records extends ElementState -{ - - @simpl_collection("Record") - @simpl_nowrap - ArrayList records; - - public Records() - { - - } -} +/* + * Created on Dec 12, 2006 + */ +package ecologylab.serialization.library.endnote; + +import java.util.ArrayList; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_nowrap; + +public @simpl_inherit class Records extends ElementState +{ + + @simpl_collection("Record") + @simpl_nowrap + ArrayList records; + + public Records() + { + + } +} diff --git a/simplCore/src/ecologylab/serialization/library/endnote/TestEndnoteXML.java b/simplCore/src/ecologylab/serialization/library/endnote/TestEndnoteXML.java index b4ded55a..ff367fc7 100644 --- a/simplCore/src/ecologylab/serialization/library/endnote/TestEndnoteXML.java +++ b/simplCore/src/ecologylab/serialization/library/endnote/TestEndnoteXML.java @@ -1,34 +1,34 @@ -/* - * Created on Dec 12, 2006 - */ -package ecologylab.serialization.library.endnote; - -import java.io.File; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -public class TestEndnoteXML -{ - - /** - * @param args - */ - public static void main(String[] args) - { - try - { - XmlState fromFile = (XmlState) EndnoteNameSpace.get().deserialize( - new File("/Users/toupsz/Desktop/RSBib.xml"), Format.XML); - - SimplTypesScope.serialize(fromFile, System.out, StringFormat.XML); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - } - -} +/* + * Created on Dec 12, 2006 + */ +package ecologylab.serialization.library.endnote; + +import java.io.File; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +public class TestEndnoteXML +{ + + /** + * @param args + */ + public static void main(String[] args) + { + try + { + XmlState fromFile = (XmlState) EndnoteNameSpace.get().deserialize( + new File("/Users/toupsz/Desktop/RSBib.xml"), Format.XML); + + SimplTypesScope.serialize(fromFile, System.out, StringFormat.XML); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/endnote/TitleList.java b/simplCore/src/ecologylab/serialization/library/endnote/TitleList.java index 3cf7bbdc..7f2fcf5b 100644 --- a/simplCore/src/ecologylab/serialization/library/endnote/TitleList.java +++ b/simplCore/src/ecologylab/serialization/library/endnote/TitleList.java @@ -1,46 +1,46 @@ -/* - * Created on Dec 12, 2006 - */ -package ecologylab.serialization.library.endnote; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.element.StringState; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public class TitleList extends ElementState -{ - private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; - - private @simpl_composite StringState secondaryTitle; - - /** - * - */ - public TitleList() - { - // TODO Auto-generated constructor stub - } - - /** - * @return the secondary_title - */ - public StringState getSecondaryTitle() - { - return secondaryTitle; - } - - /** - * @return the title - */ - public String getTitle() - { - return title; - } - -} +/* + * Created on Dec 12, 2006 + */ +package ecologylab.serialization.library.endnote; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.element.StringState; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public class TitleList extends ElementState +{ + private @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; + + private @simpl_composite StringState secondaryTitle; + + /** + * + */ + public TitleList() + { + // TODO Auto-generated constructor stub + } + + /** + * @return the secondary_title + */ + public StringState getSecondaryTitle() + { + return secondaryTitle; + } + + /** + * @return the title + */ + public String getTitle() + { + return title; + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/endnote/XmlState.java b/simplCore/src/ecologylab/serialization/library/endnote/XmlState.java index 9ea35ab5..ed66b018 100644 --- a/simplCore/src/ecologylab/serialization/library/endnote/XmlState.java +++ b/simplCore/src/ecologylab/serialization/library/endnote/XmlState.java @@ -1,42 +1,42 @@ -/* - * Created on Dec 12, 2006 - */ -package ecologylab.serialization.library.endnote; - -import java.util.ArrayList; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_collection; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public class XmlState extends ElementState -{ -// private @xml_nested Records records = new Records(); - private @simpl_collection("Record") - ArrayList records; - /** - * - */ - public XmlState() - { - } - - /** - * @return the records - */ - public ArrayList getRecords() - { - return records; - } - - /** - * @param records the records to set - */ - public void setRecords(ArrayList records) - { - this.records = records; - } - -} +/* + * Created on Dec 12, 2006 + */ +package ecologylab.serialization.library.endnote; + +import java.util.ArrayList; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_collection; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public class XmlState extends ElementState +{ +// private @xml_nested Records records = new Records(); + private @simpl_collection("Record") + ArrayList records; + /** + * + */ + public XmlState() + { + } + + /** + * @return the records + */ + public ArrayList getRecords() + { + return records; + } + + /** + * @param records the records to set + */ + public void setRecords(ArrayList records) + { + this.records = records; + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/feedburner/Feedburner.java b/simplCore/src/ecologylab/serialization/library/feedburner/Feedburner.java index bcc249fb..b98462ec 100644 --- a/simplCore/src/ecologylab/serialization/library/feedburner/Feedburner.java +++ b/simplCore/src/ecologylab/serialization/library/feedburner/Feedburner.java @@ -1,43 +1,43 @@ -/** - * - */ -package ecologylab.serialization.library.feedburner; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author andruid - * - */ -public class Feedburner extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL origLink; - - /** - * - */ - public Feedburner() - { - super(); - } - - public ParsedURL getOrigLink() - { - return origLink; - } - - public void setOrigLink(ParsedURL origLink) - { - this.origLink = origLink; - } - public static SimplTypesScope get() - { - return SimplTypesScope.get("feedburner", Feedburner.class); - } - -} +/** + * + */ +package ecologylab.serialization.library.feedburner; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author andruid + * + */ +public class Feedburner extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL origLink; + + /** + * + */ + public Feedburner() + { + super(); + } + + public ParsedURL getOrigLink() + { + return origLink; + } + + public void setOrigLink(ParsedURL origLink) + { + this.origLink = origLink; + } + public static SimplTypesScope get() + { + return SimplTypesScope.get("feedburner", Feedburner.class); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/feedburner/package.html b/simplCore/src/ecologylab/serialization/library/feedburner/package.html index 62a89409..bbcca93d 100644 --- a/simplCore/src/ecologylab/serialization/library/feedburner/package.html +++ b/simplCore/src/ecologylab/serialization/library/feedburner/package.html @@ -1,5 +1,5 @@ - -{@link ecologylab.xml.ElementState ElementState} - subclasses that enable translation of XML entities from the - Feedburner namespace. - + +{@link ecologylab.xml.ElementState ElementState} + subclasses that enable translation of XML entities from the + Feedburner namespace. + diff --git a/simplCore/src/ecologylab/serialization/library/geom/Ellipse2DDoubleState.java b/simplCore/src/ecologylab/serialization/library/geom/Ellipse2DDoubleState.java index ff6721f3..36d2ee68 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/Ellipse2DDoubleState.java +++ b/simplCore/src/ecologylab/serialization/library/geom/Ellipse2DDoubleState.java @@ -1,149 +1,149 @@ -package ecologylab.serialization.library.geom; - -import java.awt.Rectangle; -import java.awt.geom.AffineTransform; -import java.awt.geom.Ellipse2D; -import java.awt.geom.PathIterator; -import java.awt.geom.Point2D; -import java.awt.geom.Point2D.Double; -import java.awt.geom.Rectangle2D; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_other_tags; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * Encapsulates a Ellipse2D.Double for use in translating to/from XML. - * - * ***WARNING!!!*** - * - * Performing transformations (such as setFrame()) on the result of shape() will cause this object - * to become out of synch with its underlying Ellipse2D.Double object. While this will have no bad - * ramifications for this, it MAY have ramifications for what you INTENDED to do. Essentially, - * changes to the returned Shape will NOT be reflected in the XML produced by this. - * - * If other transformation methods are required, either notify me, or implement them yourself. :D - * - * Accessor methods (such as contains()) on the result of getEllipse() are fine. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -@simpl_tag("El2DD") -@simpl_other_tags("ellipse2_d_double") -public @simpl_inherit -class Ellipse2DDoubleState extends RectangularShape -{ - protected Ellipse2D.Double shape = null; - - private Double centerPoint; - - public Ellipse2DDoubleState() - { - super(); - } - - public Ellipse2DDoubleState(double x, double y, double width, double height) - { - super(x, y, width, height); - } - - public Ellipse2DDoubleState(double xCenter, double yCenter, double radius) - { - this(xCenter - radius, yCenter - radius, radius * 2.0, radius * 2.0); - } - - /** - * Returns an Ellipse2D object represented by this. - */ - @Override - public Ellipse2D.Double shape() - { - if (shape == null) - { - shape = new Ellipse2D.Double(x, y, w, h); - } - else if (shape.x != x || shape.y != y || shape.height != h || shape.width != w) - { - shape.setFrame(x, y, w, h); - } - - return shape; - } - - @Override - public boolean contains(Point2D p) - { - return shape().contains(p); - } - - @Override - public boolean contains(Rectangle2D r) - { - return shape().contains(r); - } - - @Override - public boolean contains(double x, double y) - { - return shape().contains(x, y); - } - - @Override - public boolean contains(double x, double y, double w, double h) - { - return shape().contains(x, y, w, h); - } - - @Override - public Rectangle getBounds() - { - return shape().getBounds(); - } - - @Override - public Rectangle2D getBounds2D() - { - return shape().getBounds2D(); - } - - @Override - public PathIterator getPathIterator(AffineTransform at) - { - return shape().getPathIterator(at); - } - - @Override - public PathIterator getPathIterator(AffineTransform at, double flatness) - { - return shape().getPathIterator(at, flatness); - } - - @Override - public boolean intersects(Rectangle2D r) - { - return shape().intersects(r); - } - - @Override - public boolean intersects(double x, double y, double w, double h) - { - return shape().intersects(x, y, w, h); - } - - public Point2D.Double centerPoint() - { - if (centerPoint == null) - { - synchronized (this) - { - if (centerPoint == null) - { - centerPoint = new Point2D.Double(this.getX() + (this.getWidth() / 2.0), this.getY() - + (this.getHeight() / 2.0)); - } - } - } - - return centerPoint; - } -} +package ecologylab.serialization.library.geom; + +import java.awt.Rectangle; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Point2D.Double; +import java.awt.geom.Rectangle2D; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_other_tags; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * Encapsulates a Ellipse2D.Double for use in translating to/from XML. + * + * ***WARNING!!!*** + * + * Performing transformations (such as setFrame()) on the result of shape() will cause this object + * to become out of synch with its underlying Ellipse2D.Double object. While this will have no bad + * ramifications for this, it MAY have ramifications for what you INTENDED to do. Essentially, + * changes to the returned Shape will NOT be reflected in the XML produced by this. + * + * If other transformation methods are required, either notify me, or implement them yourself. :D + * + * Accessor methods (such as contains()) on the result of getEllipse() are fine. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +@simpl_tag("El2DD") +@simpl_other_tags("ellipse2_d_double") +public @simpl_inherit +class Ellipse2DDoubleState extends RectangularShape +{ + protected Ellipse2D.Double shape = null; + + private Double centerPoint; + + public Ellipse2DDoubleState() + { + super(); + } + + public Ellipse2DDoubleState(double x, double y, double width, double height) + { + super(x, y, width, height); + } + + public Ellipse2DDoubleState(double xCenter, double yCenter, double radius) + { + this(xCenter - radius, yCenter - radius, radius * 2.0, radius * 2.0); + } + + /** + * Returns an Ellipse2D object represented by this. + */ + @Override + public Ellipse2D.Double shape() + { + if (shape == null) + { + shape = new Ellipse2D.Double(x, y, w, h); + } + else if (shape.x != x || shape.y != y || shape.height != h || shape.width != w) + { + shape.setFrame(x, y, w, h); + } + + return shape; + } + + @Override + public boolean contains(Point2D p) + { + return shape().contains(p); + } + + @Override + public boolean contains(Rectangle2D r) + { + return shape().contains(r); + } + + @Override + public boolean contains(double x, double y) + { + return shape().contains(x, y); + } + + @Override + public boolean contains(double x, double y, double w, double h) + { + return shape().contains(x, y, w, h); + } + + @Override + public Rectangle getBounds() + { + return shape().getBounds(); + } + + @Override + public Rectangle2D getBounds2D() + { + return shape().getBounds2D(); + } + + @Override + public PathIterator getPathIterator(AffineTransform at) + { + return shape().getPathIterator(at); + } + + @Override + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return shape().getPathIterator(at, flatness); + } + + @Override + public boolean intersects(Rectangle2D r) + { + return shape().intersects(r); + } + + @Override + public boolean intersects(double x, double y, double w, double h) + { + return shape().intersects(x, y, w, h); + } + + public Point2D.Double centerPoint() + { + if (centerPoint == null) + { + synchronized (this) + { + if (centerPoint == null) + { + centerPoint = new Point2D.Double(this.getX() + (this.getWidth() / 2.0), this.getY() + + (this.getHeight() / 2.0)); + } + } + } + + return centerPoint; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/geom/Line2DDoubleState.java b/simplCore/src/ecologylab/serialization/library/geom/Line2DDoubleState.java index 11727b89..efe72993 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/Line2DDoubleState.java +++ b/simplCore/src/ecologylab/serialization/library/geom/Line2DDoubleState.java @@ -1,168 +1,168 @@ -package ecologylab.serialization.library.geom; - -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.Line2D; -import java.awt.geom.PathIterator; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Encapsulates a Rectangle2D.Double for use in translating to/from XML. - * - * ***WARNING!!!*** - * - * Performing transformations (such as setFrame()) on the result of getRect() will cause this object - * to become out of synch with its underlying Rectangle2D. DO NOT DO THIS! - * - * If other transformation methods are required, either notify me, or implement them yourself. :D - * - * Accessor methods (such as contains()) on the result of getRect() are fine. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public @simpl_inherit -class Line2DDoubleState extends ElementState implements Shape -{ - @simpl_scalar - protected double x1 = 0; - - @simpl_scalar - protected double x2 = 0; - - @simpl_scalar - protected double y1 = 0; - - @simpl_scalar - protected double y2 = 0; - - private Line2D.Double line = null; - - private Vector2d normal = null; - - public Line2DDoubleState() - { - super(); - } - - public Line2DDoubleState(double x1, double y1, double x2, double y2) - { - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; - - this.computeNormal(); - - line = new Line2D.Double(x1, y1, x2, y2); - } - - public void setLine(double x1, double y1, double x2, double y2) - { - this.x1 = x1; - this.x2 = x2; - this.y1 = y1; - this.y2 = y2; - - this.computeNormal(); - - line.setLine(x1, y1, x2, y2); - } - - @Override - public boolean contains(Point2D p) - { - return line.contains(p); - } - - @Override - public boolean contains(Rectangle2D r) - { - return line.contains(r); - } - - @Override - public boolean contains(double x, double y) - { - return line.contains(x, y); - } - - @Override - public boolean contains(double x, double y, double w, double h) - { - return line.contains(x, y, w, h); - } - - @Override - public Rectangle getBounds() - { - return line.getBounds(); - } - - @Override - public Rectangle2D getBounds2D() - { - return line.getBounds2D(); - } - - @Override - public PathIterator getPathIterator(AffineTransform at) - { - return line.getPathIterator(at); - } - - @Override - public PathIterator getPathIterator(AffineTransform at, double flatness) - { - return line.getPathIterator(at, flatness); - } - - @Override - public boolean intersects(Rectangle2D r) - { - return line.intersects(r); - } - - @Override - public boolean intersects(double x, double y, double w, double h) - { - return line.intersects(x, y, w, h); - } - - /** - * Returns the normal to the plane that runs parallel to the Z-axis and through this. Computed as - * if there is a second vector (0, 0, 1) to cross with this + 0 on the z axis. - * - * @return the normal to this. - */ - public Vector2d getNormal() - { - return normal; - } - - private void computeNormal() - { - double x = x2 - x1; - double y = y2 - y1; - double z = 0; - - double pX = 0; - double pY = 0; - double pZ = 1; - - this.normal = new Vector2d(y * pZ - z * pY, z * pX - x * pZ); - } - - /** - * @return the line - */ - public Line2D.Double line() - { - return line; - } -} +package ecologylab.serialization.library.geom; + +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Encapsulates a Rectangle2D.Double for use in translating to/from XML. + * + * ***WARNING!!!*** + * + * Performing transformations (such as setFrame()) on the result of getRect() will cause this object + * to become out of synch with its underlying Rectangle2D. DO NOT DO THIS! + * + * If other transformation methods are required, either notify me, or implement them yourself. :D + * + * Accessor methods (such as contains()) on the result of getRect() are fine. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public @simpl_inherit +class Line2DDoubleState extends ElementState implements Shape +{ + @simpl_scalar + protected double x1 = 0; + + @simpl_scalar + protected double x2 = 0; + + @simpl_scalar + protected double y1 = 0; + + @simpl_scalar + protected double y2 = 0; + + private Line2D.Double line = null; + + private Vector2d normal = null; + + public Line2DDoubleState() + { + super(); + } + + public Line2DDoubleState(double x1, double y1, double x2, double y2) + { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + + this.computeNormal(); + + line = new Line2D.Double(x1, y1, x2, y2); + } + + public void setLine(double x1, double y1, double x2, double y2) + { + this.x1 = x1; + this.x2 = x2; + this.y1 = y1; + this.y2 = y2; + + this.computeNormal(); + + line.setLine(x1, y1, x2, y2); + } + + @Override + public boolean contains(Point2D p) + { + return line.contains(p); + } + + @Override + public boolean contains(Rectangle2D r) + { + return line.contains(r); + } + + @Override + public boolean contains(double x, double y) + { + return line.contains(x, y); + } + + @Override + public boolean contains(double x, double y, double w, double h) + { + return line.contains(x, y, w, h); + } + + @Override + public Rectangle getBounds() + { + return line.getBounds(); + } + + @Override + public Rectangle2D getBounds2D() + { + return line.getBounds2D(); + } + + @Override + public PathIterator getPathIterator(AffineTransform at) + { + return line.getPathIterator(at); + } + + @Override + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return line.getPathIterator(at, flatness); + } + + @Override + public boolean intersects(Rectangle2D r) + { + return line.intersects(r); + } + + @Override + public boolean intersects(double x, double y, double w, double h) + { + return line.intersects(x, y, w, h); + } + + /** + * Returns the normal to the plane that runs parallel to the Z-axis and through this. Computed as + * if there is a second vector (0, 0, 1) to cross with this + 0 on the z axis. + * + * @return the normal to this. + */ + public Vector2d getNormal() + { + return normal; + } + + private void computeNormal() + { + double x = x2 - x1; + double y = y2 - y1; + double z = 0; + + double pX = 0; + double pY = 0; + double pZ = 1; + + this.normal = new Vector2d(y * pZ - z * pY, z * pX - x * pZ); + } + + /** + * @return the line + */ + public Line2D.Double line() + { + return line; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/geom/Point2DDoubleState.java b/simplCore/src/ecologylab/serialization/library/geom/Point2DDoubleState.java index 94db0654..d97ce9f6 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/Point2DDoubleState.java +++ b/simplCore/src/ecologylab/serialization/library/geom/Point2DDoubleState.java @@ -1,88 +1,88 @@ -package ecologylab.serialization.library.geom; - -import java.awt.geom.AffineTransform; -import java.awt.geom.Point2D; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Encapsulates a Point2D.Double for use in translating to/from XML. - * - * ***WARNING!!!*** - * - * Performing transformations (such as setLocation()) on the result of getPoint() will cause this - * object to become out of synch with its underlying Point2D. DO NOT DO THIS! - * - * If other transformation methods are required, either notify me, or implement them yourself. :D - * - * Accessor methods (such as contains()) on the result of getPoint() are fine. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class Point2DDoubleState extends ElementState -{ - private Point2D.Double point = null; - - /** - * Location and dimensions of the point. - */ - protected @simpl_scalar - double x = 0; - - protected @simpl_scalar - double y = 0; - - public Point2DDoubleState() - { - super(); - } - - public Point2DDoubleState(double x, double y) - { - setLocation(x, y); - } - - public void setLocation(double x, double y) - { - this.x = x; - this.y = y; - } - - /** - * Returns an Ellipse2D object represented by this. - */ - public Point2D.Double point() - { - if (point == null) - { - point = new Point2D.Double(x, y); - } - else if (point.x != x || point.y != y) - { - point.setLocation(x, y); - } - - return point; - } - - public void transform(AffineTransform at) - { - this.point(); - - at.transform(this.point, this.point); - - this.x = this.point.x; - this.y = this.point.y; - } - - public double x() - { - return x; - } - - public double y() - { - return y; - } +package ecologylab.serialization.library.geom; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Encapsulates a Point2D.Double for use in translating to/from XML. + * + * ***WARNING!!!*** + * + * Performing transformations (such as setLocation()) on the result of getPoint() will cause this + * object to become out of synch with its underlying Point2D. DO NOT DO THIS! + * + * If other transformation methods are required, either notify me, or implement them yourself. :D + * + * Accessor methods (such as contains()) on the result of getPoint() are fine. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class Point2DDoubleState extends ElementState +{ + private Point2D.Double point = null; + + /** + * Location and dimensions of the point. + */ + protected @simpl_scalar + double x = 0; + + protected @simpl_scalar + double y = 0; + + public Point2DDoubleState() + { + super(); + } + + public Point2DDoubleState(double x, double y) + { + setLocation(x, y); + } + + public void setLocation(double x, double y) + { + this.x = x; + this.y = y; + } + + /** + * Returns an Ellipse2D object represented by this. + */ + public Point2D.Double point() + { + if (point == null) + { + point = new Point2D.Double(x, y); + } + else if (point.x != x || point.y != y) + { + point.setLocation(x, y); + } + + return point; + } + + public void transform(AffineTransform at) + { + this.point(); + + at.transform(this.point, this.point); + + this.x = this.point.x; + this.y = this.point.y; + } + + public double x() + { + return x; + } + + public double y() + { + return y; + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/library/geom/PointInt.java b/simplCore/src/ecologylab/serialization/library/geom/PointInt.java index 8a283178..1beb1d63 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/PointInt.java +++ b/simplCore/src/ecologylab/serialization/library/geom/PointInt.java @@ -1,45 +1,45 @@ -/** - * - */ -package ecologylab.serialization.library.geom; - -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author andruid - * - */ -public class PointInt -{ - @simpl_scalar - int x; - @simpl_scalar - int y; - - public PointInt() - { - - } - public PointInt(int x, int y) - { - this.x = x; - this.y = y; - } - - public int getX() - { - return x; - } - public void setX(int x) - { - this.x = x; - } - public int getY() - { - return y; - } - public void setY(int y) - { - this.y = y; - } -} +/** + * + */ +package ecologylab.serialization.library.geom; + +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author andruid + * + */ +public class PointInt +{ + @simpl_scalar + int x; + @simpl_scalar + int y; + + public PointInt() + { + + } + public PointInt(int x, int y) + { + this.x = x; + this.y = y; + } + + public int getX() + { + return x; + } + public void setX(int x) + { + this.x = x; + } + public int getY() + { + return y; + } + public void setY(int y) + { + this.y = y; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/geom/PolygonState.java b/simplCore/src/ecologylab/serialization/library/geom/PolygonState.java index 1a19dc39..01967de8 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/PolygonState.java +++ b/simplCore/src/ecologylab/serialization/library/geom/PolygonState.java @@ -1,166 +1,166 @@ -package ecologylab.serialization.library.geom; - -import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.PathIterator; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.List; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * Encapsulates a Polygon for use in translating to/from XML. - * - * ***WARNING!!!*** - * - * Performing transformations (such as setFrame()) on the result of shape() will cause this object - * to become out of synch with its underlying Rectangle2D. DO NOT DO THIS! - * - * If other transformation methods are required, either notify me, or implement them yourself. :D - * - * Accessor methods (such as contains()) on the result of getRect() are fine. - * - * @author Zachary O. Toups (zach@ecologylab.net) - * @author Alan Blevins (alan.blevins@gmail.com) - */ -public @simpl_inherit -class PolygonState extends ElementState implements Shape -{ - private Polygon shape = null; - - @simpl_collection("point2_d_double") - private ArrayList polygonVerticies = new ArrayList(); - - public PolygonState() - { - super(); - } - - public PolygonState(List verticies) - { - super(); - - definePolygon(verticies); - } - - public void definePolygon(List verticies) - { - polygonVerticies.clear(); - polygonVerticies.addAll(verticies); - - shape = null; - } - - /** - * Returns a Polygon object represented by this. - */ - public Polygon shape() - { - if (shape == null) - { - shape = new Polygon(); - for (Point2DDoubleState vert : polygonVerticies) - { - shape.addPoint((int) vert.x, (int) vert.y); - } - } - return shape; - } - - public void invalidateShape() - { - shape = null; - } - - public int numVerticies() - { - return polygonVerticies.size(); - } - - public Point2DDoubleState getVertex(int index) - { - return polygonVerticies.get(index); - } - - public boolean contains(SpatialVector v) - { - return shape().contains(v.getX(), v.getY()); - } - - @Override - public boolean contains(Point2D p) - { - return shape().contains(p); - } - - @Override - public boolean contains(Rectangle2D r) - { - return shape().contains(r); - } - - @Override - public boolean contains(double x, double y) - { - return shape().contains(x, y); - } - - @Override - public boolean contains(double x, double y, double w, double h) - { - return shape().contains(x, y, w, h); - } - - @Override - public Rectangle getBounds() - { - return shape().getBounds(); - } - - @Override - public Rectangle2D getBounds2D() - { - return shape().getBounds2D(); - } - - @Override - public PathIterator getPathIterator(AffineTransform at) - { - return shape().getPathIterator(at); - } - - @Override - public PathIterator getPathIterator(AffineTransform at, double flatness) - { - return shape().getPathIterator(at, flatness); - } - - @Override - public boolean intersects(Rectangle2D r) - { - return shape().intersects(r); - } - - @Override - public boolean intersects(double x, double y, double w, double h) - { - return shape().intersects(x, y, w, h); - } - - /** - * Returns the list of polygon vertices. Modify it at your own risk. - * - * @return polygonVerticies - */ - public ArrayList getPolygonVerticies() - { - return polygonVerticies; - } - -} +package ecologylab.serialization.library.geom; + +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * Encapsulates a Polygon for use in translating to/from XML. + * + * ***WARNING!!!*** + * + * Performing transformations (such as setFrame()) on the result of shape() will cause this object + * to become out of synch with its underlying Rectangle2D. DO NOT DO THIS! + * + * If other transformation methods are required, either notify me, or implement them yourself. :D + * + * Accessor methods (such as contains()) on the result of getRect() are fine. + * + * @author Zachary O. Toups (zach@ecologylab.net) + * @author Alan Blevins (alan.blevins@gmail.com) + */ +public @simpl_inherit +class PolygonState extends ElementState implements Shape +{ + private Polygon shape = null; + + @simpl_collection("point2_d_double") + private ArrayList polygonVerticies = new ArrayList(); + + public PolygonState() + { + super(); + } + + public PolygonState(List verticies) + { + super(); + + definePolygon(verticies); + } + + public void definePolygon(List verticies) + { + polygonVerticies.clear(); + polygonVerticies.addAll(verticies); + + shape = null; + } + + /** + * Returns a Polygon object represented by this. + */ + public Polygon shape() + { + if (shape == null) + { + shape = new Polygon(); + for (Point2DDoubleState vert : polygonVerticies) + { + shape.addPoint((int) vert.x, (int) vert.y); + } + } + return shape; + } + + public void invalidateShape() + { + shape = null; + } + + public int numVerticies() + { + return polygonVerticies.size(); + } + + public Point2DDoubleState getVertex(int index) + { + return polygonVerticies.get(index); + } + + public boolean contains(SpatialVector v) + { + return shape().contains(v.getX(), v.getY()); + } + + @Override + public boolean contains(Point2D p) + { + return shape().contains(p); + } + + @Override + public boolean contains(Rectangle2D r) + { + return shape().contains(r); + } + + @Override + public boolean contains(double x, double y) + { + return shape().contains(x, y); + } + + @Override + public boolean contains(double x, double y, double w, double h) + { + return shape().contains(x, y, w, h); + } + + @Override + public Rectangle getBounds() + { + return shape().getBounds(); + } + + @Override + public Rectangle2D getBounds2D() + { + return shape().getBounds2D(); + } + + @Override + public PathIterator getPathIterator(AffineTransform at) + { + return shape().getPathIterator(at); + } + + @Override + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return shape().getPathIterator(at, flatness); + } + + @Override + public boolean intersects(Rectangle2D r) + { + return shape().intersects(r); + } + + @Override + public boolean intersects(double x, double y, double w, double h) + { + return shape().intersects(x, y, w, h); + } + + /** + * Returns the list of polygon vertices. Modify it at your own risk. + * + * @return polygonVerticies + */ + public ArrayList getPolygonVerticies() + { + return polygonVerticies; + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/geom/Rectangle2DDoubleState.java b/simplCore/src/ecologylab/serialization/library/geom/Rectangle2DDoubleState.java index 4ece593d..304db0bf 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/Rectangle2DDoubleState.java +++ b/simplCore/src/ecologylab/serialization/library/geom/Rectangle2DDoubleState.java @@ -1,136 +1,136 @@ -package ecologylab.serialization.library.geom; - -import java.awt.Rectangle; -import java.awt.geom.AffineTransform; -import java.awt.geom.PathIterator; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; - -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * Encapsulates a Rectangle2D.Double for use in translating to/from XML. - * - * ***WARNING!!!*** - * - * Performing transformations (such as setFrame()) on the result of getRect() will cause this object - * to become out of synch with its underlying Rectangle2D. DO NOT DO THIS! - * - * If other transformation methods are required, either notify me, or implement them yourself. :D - * - * Accessor methods (such as contains()) on the result of getRect() are fine. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_inherit -public class Rectangle2DDoubleState extends RectangularShape -{ - private Rectangle2D.Double shape = null; - - private static final Vector2d[] normals = - { new Vector2d(0, -1), new Vector2d(1, 0), - new Vector2d(0, 1), new Vector2d(-1, 0) }; - - public Rectangle2DDoubleState() - { - super(); - } - - public Rectangle2DDoubleState(double x, double y, double width, double height) - { - super(x, y, width, height); - } - - /** - * Returns an Rectangle2D object represented by this. - */ - @Override - public Rectangle2D.Double shape() - { - if (shape == null) - { - shape = new Rectangle2D.Double(x, y, w, h); - } - else if (shape.x != x || shape.y != y || shape.height != h || shape.width != w) - { - shape.setFrame(x, y, w, h); - } - - return shape; - } - - @Override - public boolean contains(Point2D p) - { - return shape().contains(p); - } - - @Override - public boolean contains(Rectangle2D r) - { - return shape().contains(r); - } - - @Override - public boolean contains(double x, double y) - { - return shape().contains(x, y); - } - - @Override - public boolean contains(double x, double y, double w, double h) - { - return shape().contains(x, y, w, h); - } - - @Override - public Rectangle getBounds() - { - return shape().getBounds(); - } - - @Override - public Rectangle2D getBounds2D() - { - return shape().getBounds2D(); - } - - @Override - public PathIterator getPathIterator(AffineTransform at) - { - return shape().getPathIterator(at); - } - - @Override - public PathIterator getPathIterator(AffineTransform at, double flatness) - { - return shape().getPathIterator(at, flatness); - } - - @Override - public boolean intersects(Rectangle2D r) - { - return shape().intersects(r); - } - - @Override - public boolean intersects(double x, double y, double w, double h) - { - return shape().intersects(x, y, w, h); - } - - /** - * Determines the surface normals for each of the sides of the rectangular object. These are - * stored in an array, with entry 0 indicating the top (-y) normal, and the others progressing - * clockwise from there. - * - * The normals are assumed to lie in the X-Y plane. - * - * @return a Vector2d array with each entry corresponding to the surface normal of one of the - * sides. - */ - public static Vector2d[] getSurfaceNormals() - { - return normals; - } -} +package ecologylab.serialization.library.geom; + +import java.awt.Rectangle; +import java.awt.geom.AffineTransform; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * Encapsulates a Rectangle2D.Double for use in translating to/from XML. + * + * ***WARNING!!!*** + * + * Performing transformations (such as setFrame()) on the result of getRect() will cause this object + * to become out of synch with its underlying Rectangle2D. DO NOT DO THIS! + * + * If other transformation methods are required, either notify me, or implement them yourself. :D + * + * Accessor methods (such as contains()) on the result of getRect() are fine. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_inherit +public class Rectangle2DDoubleState extends RectangularShape +{ + private Rectangle2D.Double shape = null; + + private static final Vector2d[] normals = + { new Vector2d(0, -1), new Vector2d(1, 0), + new Vector2d(0, 1), new Vector2d(-1, 0) }; + + public Rectangle2DDoubleState() + { + super(); + } + + public Rectangle2DDoubleState(double x, double y, double width, double height) + { + super(x, y, width, height); + } + + /** + * Returns an Rectangle2D object represented by this. + */ + @Override + public Rectangle2D.Double shape() + { + if (shape == null) + { + shape = new Rectangle2D.Double(x, y, w, h); + } + else if (shape.x != x || shape.y != y || shape.height != h || shape.width != w) + { + shape.setFrame(x, y, w, h); + } + + return shape; + } + + @Override + public boolean contains(Point2D p) + { + return shape().contains(p); + } + + @Override + public boolean contains(Rectangle2D r) + { + return shape().contains(r); + } + + @Override + public boolean contains(double x, double y) + { + return shape().contains(x, y); + } + + @Override + public boolean contains(double x, double y, double w, double h) + { + return shape().contains(x, y, w, h); + } + + @Override + public Rectangle getBounds() + { + return shape().getBounds(); + } + + @Override + public Rectangle2D getBounds2D() + { + return shape().getBounds2D(); + } + + @Override + public PathIterator getPathIterator(AffineTransform at) + { + return shape().getPathIterator(at); + } + + @Override + public PathIterator getPathIterator(AffineTransform at, double flatness) + { + return shape().getPathIterator(at, flatness); + } + + @Override + public boolean intersects(Rectangle2D r) + { + return shape().intersects(r); + } + + @Override + public boolean intersects(double x, double y, double w, double h) + { + return shape().intersects(x, y, w, h); + } + + /** + * Determines the surface normals for each of the sides of the rectangular object. These are + * stored in an array, with entry 0 indicating the top (-y) normal, and the others progressing + * clockwise from there. + * + * The normals are assumed to lie in the X-Y plane. + * + * @return a Vector2d array with each entry corresponding to the surface normal of one of the + * sides. + */ + public static Vector2d[] getSurfaceNormals() + { + return normals; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/geom/Rectangular.java b/simplCore/src/ecologylab/serialization/library/geom/Rectangular.java index 98c5d6ee..40a017f0 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/Rectangular.java +++ b/simplCore/src/ecologylab/serialization/library/geom/Rectangular.java @@ -1,95 +1,95 @@ -/** - * - */ -package ecologylab.serialization.library.geom; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public abstract class Rectangular extends ElementState -{ - /** - * Location and dimensions of the ellipse. - */ - @simpl_scalar - protected double x = 0; - - @simpl_scalar - protected double y = 0; - - @simpl_scalar - protected double w = 0; - - @simpl_scalar - protected double h = 0; - - public Rectangular() - { - super(); - } - - public Rectangular(double x, double y, double width, double height) - { - super(); - - setFrame(x, y, width, height); - } - - public void setFrame(double x, double y, double w, double h) - { - this.x = x; - this.y = y; - // if we have a negative width or height, we assume the rectangle should - // just be translated to ensure that w and h are always positive - if (w < 0) - { - x += w; - w *= -1; - } - - this.w = w; - - if (h < 0) - { - y += h; - h *= -1; - } - - this.h = h; - } - - /** - * @return the h - */ - public double getHeight() - { - return h; - } - - /** - * @return the w - */ - public double getWidth() - { - return w; - } - - /** - * @return the x - */ - public double getX() - { - return x; - } - - /** - * @return the y - */ - public double getY() - { - return y; - } -} +/** + * + */ +package ecologylab.serialization.library.geom; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public abstract class Rectangular extends ElementState +{ + /** + * Location and dimensions of the ellipse. + */ + @simpl_scalar + protected double x = 0; + + @simpl_scalar + protected double y = 0; + + @simpl_scalar + protected double w = 0; + + @simpl_scalar + protected double h = 0; + + public Rectangular() + { + super(); + } + + public Rectangular(double x, double y, double width, double height) + { + super(); + + setFrame(x, y, width, height); + } + + public void setFrame(double x, double y, double w, double h) + { + this.x = x; + this.y = y; + // if we have a negative width or height, we assume the rectangle should + // just be translated to ensure that w and h are always positive + if (w < 0) + { + x += w; + w *= -1; + } + + this.w = w; + + if (h < 0) + { + y += h; + h *= -1; + } + + this.h = h; + } + + /** + * @return the h + */ + public double getHeight() + { + return h; + } + + /** + * @return the w + */ + public double getWidth() + { + return w; + } + + /** + * @return the x + */ + public double getX() + { + return x; + } + + /** + * @return the y + */ + public double getY() + { + return y; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/geom/RectangularShape.java b/simplCore/src/ecologylab/serialization/library/geom/RectangularShape.java index 40fe4f44..e7a7d524 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/RectangularShape.java +++ b/simplCore/src/ecologylab/serialization/library/geom/RectangularShape.java @@ -1,31 +1,31 @@ -/* - * Created on Aug 29, 2006 - */ -package ecologylab.serialization.library.geom; - -import java.awt.Shape; - -import ecologylab.serialization.annotations.simpl_inherit; - - - -/** - * Subclass that adds AWT. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -@simpl_inherit -public abstract class RectangularShape extends Rectangular implements Shape -{ - public RectangularShape() - { - super(); - } - - public RectangularShape(double x, double y, double width, double height) - { - super(x, y, width, height); - } - - public abstract java.awt.geom.RectangularShape shape(); -} +/* + * Created on Aug 29, 2006 + */ +package ecologylab.serialization.library.geom; + +import java.awt.Shape; + +import ecologylab.serialization.annotations.simpl_inherit; + + + +/** + * Subclass that adds AWT. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +@simpl_inherit +public abstract class RectangularShape extends Rectangular implements Shape +{ + public RectangularShape() + { + super(); + } + + public RectangularShape(double x, double y, double width, double height) + { + super(x, y, width, height); + } + + public abstract java.awt.geom.RectangularShape shape(); +} diff --git a/simplCore/src/ecologylab/serialization/library/geom/SpatialVector.java b/simplCore/src/ecologylab/serialization/library/geom/SpatialVector.java index 0f08cbd9..b189ad80 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/SpatialVector.java +++ b/simplCore/src/ecologylab/serialization/library/geom/SpatialVector.java @@ -1,25 +1,25 @@ -package ecologylab.serialization.library.geom; - -import java.awt.geom.Point2D; - -import ecologylab.serialization.ElementState; - -/** - * The base class for all the Vector classes, so that, even though they do not - * extend each other, they do extend a common class (thus, they can be used with - * generics interchangably). - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public abstract class SpatialVector extends ElementState -{ - public SpatialVector() - { - - } - - public abstract double getX(); - public abstract double getY(); - public abstract Point2D toPoint(); -} +package ecologylab.serialization.library.geom; + +import java.awt.geom.Point2D; + +import ecologylab.serialization.ElementState; + +/** + * The base class for all the Vector classes, so that, even though they do not + * extend each other, they do extend a common class (thus, they can be used with + * generics interchangably). + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public abstract class SpatialVector extends ElementState +{ + public SpatialVector() + { + + } + + public abstract double getX(); + public abstract double getY(); + public abstract Point2D toPoint(); +} diff --git a/simplCore/src/ecologylab/serialization/library/geom/TestFloats.java b/simplCore/src/ecologylab/serialization/library/geom/TestFloats.java index 39e7febe..d0497478 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/TestFloats.java +++ b/simplCore/src/ecologylab/serialization/library/geom/TestFloats.java @@ -1,30 +1,30 @@ -/* - * Created on Nov 14, 2006 - */ -package ecologylab.serialization.library.geom; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public @simpl_inherit class TestFloats extends ElementState implements Cloneable -{ - protected @simpl_scalar float y = 0; - - /** - * - */ - public TestFloats() - { - super(); - } - - public TestFloats(float y) - { - this.y = y; - } - -} +/* + * Created on Nov 14, 2006 + */ +package ecologylab.serialization.library.geom; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public @simpl_inherit class TestFloats extends ElementState implements Cloneable +{ + protected @simpl_scalar float y = 0; + + /** + * + */ + public TestFloats() + { + super(); + } + + public TestFloats(float y) + { + this.y = y; + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/geom/Vector2d.java b/simplCore/src/ecologylab/serialization/library/geom/Vector2d.java index 62809d88..f2f81987 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/Vector2d.java +++ b/simplCore/src/ecologylab/serialization/library/geom/Vector2d.java @@ -1,314 +1,314 @@ -/* - * Created on Nov 14, 2006 - */ -package ecologylab.serialization.library.geom; - -import java.awt.geom.Point2D; - -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public class Vector2d extends SpatialVector implements Cloneable -{ - /** - * Adds two vectors together and returns a new Vector2d object representing the sum. - * - * @param v1 - * @param v2 - * @return - */ - public static Vector2d add(Vector2d v1, Vector2d v2) - { - return new Vector2d(v1.getX() + v2.getX(), v1.getY() + v2.getY()); - } - - /** - * Multiplies a vector by a scalar value and returns a new Vector2d representing the result. - * - * @param vector - * @param scalar - * @return - */ - public static Vector2d scalarMultiply(Vector2d vector, double scalar) - { - return new Vector2d(vector.getX() * scalar, vector.getY() * scalar); - } - - /** - * Determines the dot product of two vector objects. - * - * @param v1 - * @param v2 - * @return - */ - public static double dot(Vector2d v1, Vector2d v2) - { - return (v1.getX() * v2.getX()) + (v1.getY() * v2.getY()); - } - - /** - * Subtracts v2 from v1 and returns a new Vector2d representing the result. - * - * @param v1 - * @param v2 - * @return - */ - public static Vector2d sub(SpatialVector v1, SpatialVector v2) - { - return new Vector2d(v1.getX() - v2.getX(), v1.getY() - v2.getY()); - } - - protected @simpl_scalar - double x; - - protected @simpl_scalar - double y; - - protected Point2D.Double point = null; - - /** - * - */ - public Vector2d() - { - super(); - - // zero(); - } - - public Vector2d(double x, double y) - { - this.x = x; - this.y = y; - } - - public Vector2d(Vector2d otherVect) - { - x = otherVect.getX(); - y = otherVect.getY(); - } - - public void add(Vector2d v) - { - this.scaledAdd(v, 1.0); - } - - /** - * Scale a vector and add it to this. - * - * @param v - * the vector to be scaled and added to this. - * @param scale - * the scale for the vector to be added. - */ - public void scaledAdd(Vector2d v, double scale) - { - this.x += v.getX() * scale; - this.y += v.getY() * scale; - - updatePointIfNotNull(); - } - - public double norm() - { - return Math.sqrt(x * x + y * y); - } - - public void mult(double scalar) - { - this.x *= scalar; - this.y *= scalar; - - updatePointIfNotNull(); - } - - /** - * Rotates this vector around the origin by the specified angle in degrees. - * - * @param angle - * - in radians - */ - public void rotate(double angle) - { - double cos = Math.cos(angle); - double sin = Math.sin(angle); - - double x1 = this.x; - double y1 = this.y; - - this.x = (x1 * cos) - (y1 * sin); - this.y = (y1 * cos) + (x1 * sin); - - updatePointIfNotNull(); - } - - /** - * Rotates this vector so that it is aligned to the specified angle in radians. - * - * @param angle - * - in radians - */ - public void rotateTo(double angle) - { - // TODO gotta make this more efficient! - this.rotate(angle - this.toRadians()); - } - - public void sub(Vector2d v) - { - this.x -= v.getX(); - this.y -= v.getY(); - - updatePointIfNotNull(); - } - - /** - * Converts the vector into a radian angle. If the result would be NaN, returns 0. - * - * @return - */ - public double toRadians() - { - double result = Math.atan2(y, x); - - if (Double.isNaN(result)) - result = 0; - - return result; - } - - public Vector2d unitVector() - { - double mag = this.norm(); - - return new Vector2d(this.x / mag, this.y / mag); - } - - public void unitize() - { - double mag = this.norm(); - - this.set(this.x / mag, this.y / mag); - } - - /** - * @see java.lang.Object#clone() - */ - @Override - public Vector2d clone() - { - return new Vector2d(this); - } - - public void set(Vector2d pos) - { - this.set(pos.getX(), pos.getY()); - } - - @Override - public Point2D toPoint() - { - if (this.point == null) - point = new Point2D.Double(x, y); - - return point; - } - - /** - * @see ecologylab.generic.Debug#toString() - */ - @Override - public String toString() - { - return "(" + x + ", " + y + ")"; - } - - /** - * Adjusts the magnitude of this vector to match mag. - * - * @param mag - */ - public void setNorm(double mag) - { - this.unitize(); - this.mult(mag); - } - - public void zero() - { - x = 0; - y = 0; - } - - public void set(double x, double y) - { - this.x = x; - this.y = y; - - updatePointIfNotNull(); - } - - /** - * @param x - */ - private void updatePointIfNotNull() - { - if (this.point != null) - { - synchronized (point) - { - point.setLocation(x, y); - } - } - } - - /** - * @param y - * the y to set - */ - public void setX(double x) - { - this.x = x; - - updatePointIfNotNull(); - } - - /** - * @param y - * the y to set - */ - public void setY(double y) - { - this.y = y; - - updatePointIfNotNull(); - } - - /** - * @return the x - */ - @Override - public double getX() - { - return x; - } - - /** - * @return the y - */ - @Override - public double getY() - { - return y; - } - - public void add(double x, double y) - { - this.x += x; - this.y += y; - - updatePointIfNotNull(); - } +/* + * Created on Nov 14, 2006 + */ +package ecologylab.serialization.library.geom; + +import java.awt.geom.Point2D; + +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public class Vector2d extends SpatialVector implements Cloneable +{ + /** + * Adds two vectors together and returns a new Vector2d object representing the sum. + * + * @param v1 + * @param v2 + * @return + */ + public static Vector2d add(Vector2d v1, Vector2d v2) + { + return new Vector2d(v1.getX() + v2.getX(), v1.getY() + v2.getY()); + } + + /** + * Multiplies a vector by a scalar value and returns a new Vector2d representing the result. + * + * @param vector + * @param scalar + * @return + */ + public static Vector2d scalarMultiply(Vector2d vector, double scalar) + { + return new Vector2d(vector.getX() * scalar, vector.getY() * scalar); + } + + /** + * Determines the dot product of two vector objects. + * + * @param v1 + * @param v2 + * @return + */ + public static double dot(Vector2d v1, Vector2d v2) + { + return (v1.getX() * v2.getX()) + (v1.getY() * v2.getY()); + } + + /** + * Subtracts v2 from v1 and returns a new Vector2d representing the result. + * + * @param v1 + * @param v2 + * @return + */ + public static Vector2d sub(SpatialVector v1, SpatialVector v2) + { + return new Vector2d(v1.getX() - v2.getX(), v1.getY() - v2.getY()); + } + + protected @simpl_scalar + double x; + + protected @simpl_scalar + double y; + + protected Point2D.Double point = null; + + /** + * + */ + public Vector2d() + { + super(); + + // zero(); + } + + public Vector2d(double x, double y) + { + this.x = x; + this.y = y; + } + + public Vector2d(Vector2d otherVect) + { + x = otherVect.getX(); + y = otherVect.getY(); + } + + public void add(Vector2d v) + { + this.scaledAdd(v, 1.0); + } + + /** + * Scale a vector and add it to this. + * + * @param v + * the vector to be scaled and added to this. + * @param scale + * the scale for the vector to be added. + */ + public void scaledAdd(Vector2d v, double scale) + { + this.x += v.getX() * scale; + this.y += v.getY() * scale; + + updatePointIfNotNull(); + } + + public double norm() + { + return Math.sqrt(x * x + y * y); + } + + public void mult(double scalar) + { + this.x *= scalar; + this.y *= scalar; + + updatePointIfNotNull(); + } + + /** + * Rotates this vector around the origin by the specified angle in degrees. + * + * @param angle + * - in radians + */ + public void rotate(double angle) + { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + + double x1 = this.x; + double y1 = this.y; + + this.x = (x1 * cos) - (y1 * sin); + this.y = (y1 * cos) + (x1 * sin); + + updatePointIfNotNull(); + } + + /** + * Rotates this vector so that it is aligned to the specified angle in radians. + * + * @param angle + * - in radians + */ + public void rotateTo(double angle) + { + // TODO gotta make this more efficient! + this.rotate(angle - this.toRadians()); + } + + public void sub(Vector2d v) + { + this.x -= v.getX(); + this.y -= v.getY(); + + updatePointIfNotNull(); + } + + /** + * Converts the vector into a radian angle. If the result would be NaN, returns 0. + * + * @return + */ + public double toRadians() + { + double result = Math.atan2(y, x); + + if (Double.isNaN(result)) + result = 0; + + return result; + } + + public Vector2d unitVector() + { + double mag = this.norm(); + + return new Vector2d(this.x / mag, this.y / mag); + } + + public void unitize() + { + double mag = this.norm(); + + this.set(this.x / mag, this.y / mag); + } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Vector2d clone() + { + return new Vector2d(this); + } + + public void set(Vector2d pos) + { + this.set(pos.getX(), pos.getY()); + } + + @Override + public Point2D toPoint() + { + if (this.point == null) + point = new Point2D.Double(x, y); + + return point; + } + + /** + * @see ecologylab.generic.Debug#toString() + */ + @Override + public String toString() + { + return "(" + x + ", " + y + ")"; + } + + /** + * Adjusts the magnitude of this vector to match mag. + * + * @param mag + */ + public void setNorm(double mag) + { + this.unitize(); + this.mult(mag); + } + + public void zero() + { + x = 0; + y = 0; + } + + public void set(double x, double y) + { + this.x = x; + this.y = y; + + updatePointIfNotNull(); + } + + /** + * @param x + */ + private void updatePointIfNotNull() + { + if (this.point != null) + { + synchronized (point) + { + point.setLocation(x, y); + } + } + } + + /** + * @param y + * the y to set + */ + public void setX(double x) + { + this.x = x; + + updatePointIfNotNull(); + } + + /** + * @param y + * the y to set + */ + public void setY(double y) + { + this.y = y; + + updatePointIfNotNull(); + } + + /** + * @return the x + */ + @Override + public double getX() + { + return x; + } + + /** + * @return the y + */ + @Override + public double getY() + { + return y; + } + + public void add(double x, double y) + { + this.x += x; + this.y += y; + + updatePointIfNotNull(); + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/library/geom/Vector2dFloat.java b/simplCore/src/ecologylab/serialization/library/geom/Vector2dFloat.java index b1d0ecc4..bd459006 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/Vector2dFloat.java +++ b/simplCore/src/ecologylab/serialization/library/geom/Vector2dFloat.java @@ -1,279 +1,279 @@ -/* - * Created on Nov 14, 2006 - */ -package ecologylab.serialization.library.geom; - -import java.awt.geom.Point2D; - -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public @simpl_tag("vect2df") class Vector2dFloat extends SpatialVector implements - Cloneable -{ - /** - * Adds two vectors together and returns a new Vector2d object representing - * the sum. - * - * @param v1 - * @param v2 - * @return - */ - public static Vector2dFloat add(Vector2dFloat v1, Vector2dFloat v2) - { - return new Vector2dFloat(v1.x + v2.x, v1.y + v2.y); - } - - /** - * Multiplies a vector by a scalar value and returns a new Vector2d - * representing the result. - * - * @param vector - * @param scalar - * @return - */ - public static Vector2dFloat scalarMultiply(Vector2dFloat vector, float scalar) - { - return new Vector2dFloat(vector.x * scalar, vector.y * scalar); - } - - /** - * Determines the dot product of two vector objects. - * - * @param v1 - * @param v2 - * @return - */ - public static float dot(Vector2dFloat v1, Vector2dFloat v2) - { - return (v1.x * v2.x) + (v1.y * v2.y); - } - - /** - * Subtracts v2 from v1 and returns a new Vector2d representing the result. - * - * @param v1 - * @param v2 - * @return - */ - public static Vector2dFloat sub(Vector2dFloat v1, Vector2dFloat v2) - { - return new Vector2dFloat(v1.x - v2.x, v1.y - v2.y); - } - - protected @simpl_scalar float x; - - protected @simpl_scalar float y; - - protected Point2D.Float point = null; - - /** - * - */ - public Vector2dFloat() - { - super(); - } - - public Vector2dFloat(float x, float y) - { - this.x = x; - this.y = y; - } - - public Vector2dFloat(Vector2dFloat otherVect) - { - x = otherVect.x; - y = otherVect.y; - } - - public void add(Vector2dFloat v) - { - this.x += v.getX(); - this.y += v.getY(); - - updatePointIfNotNull(); - } - - public double norm() - { - return Math.sqrt(x * x + y * y); - } - - public void mult(float scalar) - { - this.x *= scalar; - this.y *= scalar; - - updatePointIfNotNull(); - } - - /** - * Rotates this vector around the origin by the specified angle in degrees. - * - * @param angle - - * in radians - */ - public void rotate(double angle) - { - double cos = Math.cos(angle); - double sin = Math.sin(angle); - - float x1 = this.x; - float y1 = this.y; - - this.x = (float) ((x1 * cos) - (y1 * sin)); - this.y = (float) ((y1 * cos) + (x1 * sin)); - - updatePointIfNotNull(); - } - - /** - * Rotates this vector so that it is aligned to the specified angle in - * radians. - * - * @param angle - - * in radians - */ - public void rotateTo(float angle) - { - // TODO gotta make this more efficient! - this.rotate(angle - this.toRadians()); - } - - public void sub(Vector2dFloat v) - { - this.x -= v.getX(); - this.y -= v.getY(); - - updatePointIfNotNull(); - } - - /** - * Converts the vector into a radian angle. If the result would be NaN, - * returns 0. - * - * @return - */ - public double toRadians() - { - double result = Math.atan2(y, x); - - if (Double.isNaN(result)) - result = 0; - - return result; - } - - public Vector2dFloat unitVector() - { - double mag = this.norm(); - - return new Vector2dFloat((float) (this.x / mag), (float) (this.y / mag)); - } - - public void unitize() - { - double mag = this.norm(); - - this.set((float) (this.x / mag), (float) (this.y / mag)); - } - - /** - * @see java.lang.Object#clone() - */ - @Override public Vector2dFloat clone() - { - return new Vector2dFloat(this); - } - - public void set(Vector2dFloat pos) - { - this.set(pos.x, pos.y); - } - - @Override public Point2D toPoint() - { - if (this.point == null) - point = new Point2D.Float(x, y); - - return point; - } - - /** - * @see ecologylab.generic.Debug#toString() - */ - @Override public String toString() - { - return "(" + x + ", " + y + ")"; - } - - /** - * Adjusts the magnitude of this vector to match mag. - * - * @param mag - */ - public void setNorm(float mag) - { - this.unitize(); - this.mult(mag); - } - - public void zero() - { - x = 0; - y = 0; - } - - public void set(float x, float y) - { - this.x = x; - this.y = y; - - updatePointIfNotNull(); - } - - /** - * @param x - */ - private void updatePointIfNotNull() - { - if (this.point != null) - { - synchronized (point) - { - point.setLocation(x, y); - } - } - } - - /** - * @param y - * the y to set - */ - public void setY(float y) - { - this.y = y; - - updatePointIfNotNull(); - } - - /** - * @return the x - */ - @Override public double getX() - { - return x; - } - - /** - * @return the y - */ - @Override public double getY() - { - return y; - } +/* + * Created on Nov 14, 2006 + */ +package ecologylab.serialization.library.geom; + +import java.awt.geom.Point2D; + +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public @simpl_tag("vect2df") class Vector2dFloat extends SpatialVector implements + Cloneable +{ + /** + * Adds two vectors together and returns a new Vector2d object representing + * the sum. + * + * @param v1 + * @param v2 + * @return + */ + public static Vector2dFloat add(Vector2dFloat v1, Vector2dFloat v2) + { + return new Vector2dFloat(v1.x + v2.x, v1.y + v2.y); + } + + /** + * Multiplies a vector by a scalar value and returns a new Vector2d + * representing the result. + * + * @param vector + * @param scalar + * @return + */ + public static Vector2dFloat scalarMultiply(Vector2dFloat vector, float scalar) + { + return new Vector2dFloat(vector.x * scalar, vector.y * scalar); + } + + /** + * Determines the dot product of two vector objects. + * + * @param v1 + * @param v2 + * @return + */ + public static float dot(Vector2dFloat v1, Vector2dFloat v2) + { + return (v1.x * v2.x) + (v1.y * v2.y); + } + + /** + * Subtracts v2 from v1 and returns a new Vector2d representing the result. + * + * @param v1 + * @param v2 + * @return + */ + public static Vector2dFloat sub(Vector2dFloat v1, Vector2dFloat v2) + { + return new Vector2dFloat(v1.x - v2.x, v1.y - v2.y); + } + + protected @simpl_scalar float x; + + protected @simpl_scalar float y; + + protected Point2D.Float point = null; + + /** + * + */ + public Vector2dFloat() + { + super(); + } + + public Vector2dFloat(float x, float y) + { + this.x = x; + this.y = y; + } + + public Vector2dFloat(Vector2dFloat otherVect) + { + x = otherVect.x; + y = otherVect.y; + } + + public void add(Vector2dFloat v) + { + this.x += v.getX(); + this.y += v.getY(); + + updatePointIfNotNull(); + } + + public double norm() + { + return Math.sqrt(x * x + y * y); + } + + public void mult(float scalar) + { + this.x *= scalar; + this.y *= scalar; + + updatePointIfNotNull(); + } + + /** + * Rotates this vector around the origin by the specified angle in degrees. + * + * @param angle - + * in radians + */ + public void rotate(double angle) + { + double cos = Math.cos(angle); + double sin = Math.sin(angle); + + float x1 = this.x; + float y1 = this.y; + + this.x = (float) ((x1 * cos) - (y1 * sin)); + this.y = (float) ((y1 * cos) + (x1 * sin)); + + updatePointIfNotNull(); + } + + /** + * Rotates this vector so that it is aligned to the specified angle in + * radians. + * + * @param angle - + * in radians + */ + public void rotateTo(float angle) + { + // TODO gotta make this more efficient! + this.rotate(angle - this.toRadians()); + } + + public void sub(Vector2dFloat v) + { + this.x -= v.getX(); + this.y -= v.getY(); + + updatePointIfNotNull(); + } + + /** + * Converts the vector into a radian angle. If the result would be NaN, + * returns 0. + * + * @return + */ + public double toRadians() + { + double result = Math.atan2(y, x); + + if (Double.isNaN(result)) + result = 0; + + return result; + } + + public Vector2dFloat unitVector() + { + double mag = this.norm(); + + return new Vector2dFloat((float) (this.x / mag), (float) (this.y / mag)); + } + + public void unitize() + { + double mag = this.norm(); + + this.set((float) (this.x / mag), (float) (this.y / mag)); + } + + /** + * @see java.lang.Object#clone() + */ + @Override public Vector2dFloat clone() + { + return new Vector2dFloat(this); + } + + public void set(Vector2dFloat pos) + { + this.set(pos.x, pos.y); + } + + @Override public Point2D toPoint() + { + if (this.point == null) + point = new Point2D.Float(x, y); + + return point; + } + + /** + * @see ecologylab.generic.Debug#toString() + */ + @Override public String toString() + { + return "(" + x + ", " + y + ")"; + } + + /** + * Adjusts the magnitude of this vector to match mag. + * + * @param mag + */ + public void setNorm(float mag) + { + this.unitize(); + this.mult(mag); + } + + public void zero() + { + x = 0; + y = 0; + } + + public void set(float x, float y) + { + this.x = x; + this.y = y; + + updatePointIfNotNull(); + } + + /** + * @param x + */ + private void updatePointIfNotNull() + { + if (this.point != null) + { + synchronized (point) + { + point.setLocation(x, y); + } + } + } + + /** + * @param y + * the y to set + */ + public void setY(float y) + { + this.y = y; + + updatePointIfNotNull(); + } + + /** + * @return the x + */ + @Override public double getX() + { + return x; + } + + /** + * @return the y + */ + @Override public double getY() + { + return y; + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/library/geom/package.html b/simplCore/src/ecologylab/serialization/library/geom/package.html index efff406e..b8809eea 100644 --- a/simplCore/src/ecologylab/serialization/library/geom/package.html +++ b/simplCore/src/ecologylab/serialization/library/geom/package.html @@ -1,5 +1,5 @@ - - {@link ecologylab.xml.ElementState ElementState} subclasses - that enable transferring information about geometry, such - as 2D vectors or shapes. + + {@link ecologylab.xml.ElementState ElementState} subclasses + that enable transferring information about geometry, such + as 2D vectors or shapes. \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/library/icdl/Book.java b/simplCore/src/ecologylab/serialization/library/icdl/Book.java index 2ef39c4f..3afd5e69 100644 --- a/simplCore/src/ecologylab/serialization/library/icdl/Book.java +++ b/simplCore/src/ecologylab/serialization/library/icdl/Book.java @@ -1,205 +1,205 @@ -/** - * - */ -package ecologylab.serialization.library.icdl; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Book item in ICDL BookXMLResults response. - * - * http://www.childrenslibrary.org/icdl/BookXMLResults?ids=133,265&prefcollids=474&lang=English&sort=title&ptype=simple - * - * ids: 113 comic_book http://www.childrenslibrary.org/library/basic/images/action_adventure_round.gifhttp://www.childrenslibrary.org/library/basic/images/comic_book_round.gif - * 133 make_believe_books - * 163 action_adventure http://www.childrenslibrary.org/library/basic/images/action_adventure_round.gif - * 170 poetry - * 155 mythology_folktales - * 166 science_fiction_fantasy - * 168 funny / humorous * - * 167 scary / horror * - * 169 fairy tales and folk tales fairy_folk_tales_round - * 265 award winning * - * 418 recently added newbooks_round - * 300 imaginary creature characters imaginary_beasts_creature_round - * 303 kid characters kids_round - * 301 real animal characters animals_round - * - * 16 picture books - * - * fairy_folk_tales_round_over - * - * @author andruid - */ -public class Book extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String id; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String booktitle; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String languages; - - /** - * Location of a thumbnail image for the cover of this book. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL cover; - /** - * Width of the cover image. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) int width; - /** - * Height of the cover image. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) int height; - - /** - * Evidently supposed to enable browsing the book. But it doesn't work. - * - * What they provide looks like: - * http://www.childrenslibrary.org/icdl/BookPreview?bookid=yusoldm_00500219&summary=true&categories=false&route=simple_133,265_0_0_English_0&lang=English&msg= - * - * What works looks like: - * http://www.childrenslibrary.org/icdl/BookPreview?bookid=hergran_00030022&summary=true&categories=false&route=simple_0_0_0_English_0&lang=English&msg= - * - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL bookurl; - - - /** - * - */ - public Book() - { - super(); - - } - - - /** - * @return Returns the booktitle. - */ - public String getBooktitle() - { - return booktitle; - } - - - /** - * @param booktitle The booktitle to set. - */ - public void setBooktitle(String booktitle) - { - this.booktitle = booktitle; - } - - - /** - * @return Returns the bookurl. - */ - public ParsedURL getBookurl() - { - return bookurl; - } - - - /** - * @param bookurl The bookurl to set. - */ - public void setBookurl(ParsedURL bookurl) - { - this.bookurl = bookurl; - } - - - /** - * @return Returns the cover. - */ - public ParsedURL getCover() - { - return cover; - } - - - /** - * @param cover The cover to set. - */ - public void setCover(ParsedURL cover) - { - this.cover = cover; - } - - - /** - * @return Returns the height. - */ - public int getHeight() - { - return height; - } - - - /** - * @param height The height to set. - */ - public void setHeight(int height) - { - this.height = height; - } - - - /** - * @return Returns the id. - */ - public String getId() - { - return id; - } - - - /** - * @param id The id to set. - */ - public void setId(String id) - { - this.id = id; - } - - - /** - * @return Returns the languages. - */ - public String getLanguages() - { - return languages; - } - - - /** - * @param languages The languages to set. - */ - public void setLanguages(String languages) - { - this.languages = languages; - } - - - /** - * @return Returns the width. - */ - public int getWidth() - { - return width; - } - - - /** - * @param width The width to set. - */ - public void setWidth(int width) - { - this.width = width; - } - -} +/** + * + */ +package ecologylab.serialization.library.icdl; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Book item in ICDL BookXMLResults response. + * + * http://www.childrenslibrary.org/icdl/BookXMLResults?ids=133,265&prefcollids=474&lang=English&sort=title&ptype=simple + * + * ids: 113 comic_book http://www.childrenslibrary.org/library/basic/images/action_adventure_round.gifhttp://www.childrenslibrary.org/library/basic/images/comic_book_round.gif + * 133 make_believe_books + * 163 action_adventure http://www.childrenslibrary.org/library/basic/images/action_adventure_round.gif + * 170 poetry + * 155 mythology_folktales + * 166 science_fiction_fantasy + * 168 funny / humorous * + * 167 scary / horror * + * 169 fairy tales and folk tales fairy_folk_tales_round + * 265 award winning * + * 418 recently added newbooks_round + * 300 imaginary creature characters imaginary_beasts_creature_round + * 303 kid characters kids_round + * 301 real animal characters animals_round + * + * 16 picture books + * + * fairy_folk_tales_round_over + * + * @author andruid + */ +public class Book extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String id; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String booktitle; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String languages; + + /** + * Location of a thumbnail image for the cover of this book. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL cover; + /** + * Width of the cover image. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) int width; + /** + * Height of the cover image. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) int height; + + /** + * Evidently supposed to enable browsing the book. But it doesn't work. + * + * What they provide looks like: + * http://www.childrenslibrary.org/icdl/BookPreview?bookid=yusoldm_00500219&summary=true&categories=false&route=simple_133,265_0_0_English_0&lang=English&msg= + * + * What works looks like: + * http://www.childrenslibrary.org/icdl/BookPreview?bookid=hergran_00030022&summary=true&categories=false&route=simple_0_0_0_English_0&lang=English&msg= + * + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL bookurl; + + + /** + * + */ + public Book() + { + super(); + + } + + + /** + * @return Returns the booktitle. + */ + public String getBooktitle() + { + return booktitle; + } + + + /** + * @param booktitle The booktitle to set. + */ + public void setBooktitle(String booktitle) + { + this.booktitle = booktitle; + } + + + /** + * @return Returns the bookurl. + */ + public ParsedURL getBookurl() + { + return bookurl; + } + + + /** + * @param bookurl The bookurl to set. + */ + public void setBookurl(ParsedURL bookurl) + { + this.bookurl = bookurl; + } + + + /** + * @return Returns the cover. + */ + public ParsedURL getCover() + { + return cover; + } + + + /** + * @param cover The cover to set. + */ + public void setCover(ParsedURL cover) + { + this.cover = cover; + } + + + /** + * @return Returns the height. + */ + public int getHeight() + { + return height; + } + + + /** + * @param height The height to set. + */ + public void setHeight(int height) + { + this.height = height; + } + + + /** + * @return Returns the id. + */ + public String getId() + { + return id; + } + + + /** + * @param id The id to set. + */ + public void setId(String id) + { + this.id = id; + } + + + /** + * @return Returns the languages. + */ + public String getLanguages() + { + return languages; + } + + + /** + * @param languages The languages to set. + */ + public void setLanguages(String languages) + { + this.languages = languages; + } + + + /** + * @return Returns the width. + */ + public int getWidth() + { + return width; + } + + + /** + * @param width The width to set. + */ + public void setWidth(int width) + { + this.width = width; + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/icdl/ICDLTranslations.java b/simplCore/src/ecologylab/serialization/library/icdl/ICDLTranslations.java index 8f49c5ef..2dc614a8 100644 --- a/simplCore/src/ecologylab/serialization/library/icdl/ICDLTranslations.java +++ b/simplCore/src/ecologylab/serialization/library/icdl/ICDLTranslations.java @@ -1,36 +1,36 @@ -/** - * - */ -package ecologylab.serialization.library.icdl; - -import ecologylab.generic.Debug; -import ecologylab.serialization.SimplTypesScope; - -/** - * Translations for parsing International Childrens Digital Library stuff. - * - * @author andruid - */ -public class ICDLTranslations extends Debug -{ - private static final String TRANSLATION_SPACE_NAME = "icdl"; - private static final String PACKAGE_NAME = "ecologylab.serialization.library.icdl"; - - public static final Class TRANSLATIONS[] = - { - Response.class, - Book.class, - }; - - /** - * Just prevent anyone from new'ing this. - */ - private ICDLTranslations() - { - } - - public static SimplTypesScope get() - { - return SimplTypesScope.get(TRANSLATION_SPACE_NAME, TRANSLATIONS); - } -} +/** + * + */ +package ecologylab.serialization.library.icdl; + +import ecologylab.generic.Debug; +import ecologylab.serialization.SimplTypesScope; + +/** + * Translations for parsing International Childrens Digital Library stuff. + * + * @author andruid + */ +public class ICDLTranslations extends Debug +{ + private static final String TRANSLATION_SPACE_NAME = "icdl"; + private static final String PACKAGE_NAME = "ecologylab.serialization.library.icdl"; + + public static final Class TRANSLATIONS[] = + { + Response.class, + Book.class, + }; + + /** + * Just prevent anyone from new'ing this. + */ + private ICDLTranslations() + { + } + + public static SimplTypesScope get() + { + return SimplTypesScope.get(TRANSLATION_SPACE_NAME, TRANSLATIONS); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/icdl/Response.java b/simplCore/src/ecologylab/serialization/library/icdl/Response.java index 42a5ea29..4350cf68 100644 --- a/simplCore/src/ecologylab/serialization/library/icdl/Response.java +++ b/simplCore/src/ecologylab/serialization/library/icdl/Response.java @@ -1,49 +1,49 @@ -/** - * - */ -package ecologylab.serialization.library.icdl; - -import java.util.ArrayList; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -/** - * The root element in a reply to ICDL BookXMLResults. - * - * http://www.childrenslibrary.org/icdl/BookXMLResults?ids=133,265&viewids=&prefcollids=474&langid=&text=&lang=English&match=all&sort=title&pnum=1&pgct=8&ptype=simple - * can be reduced to - * http://www.childrenslibrary.org/icdl/BookXMLResults?ids=133,265&prefcollids=474&lang=English&sort=title&ptype=simple - * @author andruid - */ -@simpl_inherit -public class Response extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) int pnum; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) int total; - - @simpl_collection("Book") - @simpl_nowrap - ArrayList books; - - /** - * - */ - public Response() - { - super(); - - } - - public ArrayList getBooks() - { - if (books != null) - return books; - return books = new ArrayList(); - } - -} +/** + * + */ +package ecologylab.serialization.library.icdl; + +import java.util.ArrayList; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +/** + * The root element in a reply to ICDL BookXMLResults. + * + * http://www.childrenslibrary.org/icdl/BookXMLResults?ids=133,265&viewids=&prefcollids=474&langid=&text=&lang=English&match=all&sort=title&pnum=1&pgct=8&ptype=simple + * can be reduced to + * http://www.childrenslibrary.org/icdl/BookXMLResults?ids=133,265&prefcollids=474&lang=English&sort=title&ptype=simple + * @author andruid + */ +@simpl_inherit +public class Response extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) int pnum; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) int total; + + @simpl_collection("Book") + @simpl_nowrap + ArrayList books; + + /** + * + */ + public Response() + { + super(); + + } + + public ArrayList getBooks() + { + if (books != null) + return books; + return books = new ArrayList(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/itunes/Itunes.java b/simplCore/src/ecologylab/serialization/library/itunes/Itunes.java index 626cb067..bd22ae4f 100644 --- a/simplCore/src/ecologylab/serialization/library/itunes/Itunes.java +++ b/simplCore/src/ecologylab/serialization/library/itunes/Itunes.java @@ -1,90 +1,90 @@ -package ecologylab.serialization.library.itunes; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * XMLNS (namespace) corresponding to itunes podcasts. - * - * http://www.apple.com/itunes/podcasts/techspecs.html - * - * It seems that between them, apple and yahoo should have one standard. - * They suck for having two similar but different ones. - * - * @author andruid - */ -public class Itunes extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String subtitle; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String author; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String summary; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL image; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String duration; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String keywords; - //public Owner owner; subfields -- email, name - /** - * @return Returns the author. - */ - protected String getAuthor() - { - return author; - } - /** - * @return Returns the duration. - */ - protected String getDuration() - { - return duration; - } - /** - * @return Returns the image. - */ - protected ParsedURL getImage() - { - return image; - } - /** - * @return Returns the keywords. - */ - protected String getKeywords() - { - return keywords; - } - /** - * @return Returns the subtitle. - */ - protected String getSubtitle() - { - return subtitle; - } - /** - * @return Returns the summary. - */ - protected String getSummary() - { - return summary; - } - - /** - * Cateogory is a yuck field to define semantically, because there - * can be a single one at top level. - * There can be multiple ones at top level. - * And, additionally, they can be nested. It seems that in practice, - * their categories hierarchy only goes one deep at this time. - *

- * Yuck! - *

- * It seems that these are quite similar to the Category sub-element of - * media:content, except that - * 1) these can be nested - * 2) these use an attribute field named "text", instead of functioning as - * plain old leaf nodes. Triple yuck. - */ - //public Category cateogry; - - // public String explicit; - -} +package ecologylab.serialization.library.itunes; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * XMLNS (namespace) corresponding to itunes podcasts. + * + * http://www.apple.com/itunes/podcasts/techspecs.html + * + * It seems that between them, apple and yahoo should have one standard. + * They suck for having two similar but different ones. + * + * @author andruid + */ +public class Itunes extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String subtitle; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String author; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String summary; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL image; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String duration; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String keywords; + //public Owner owner; subfields -- email, name + /** + * @return Returns the author. + */ + protected String getAuthor() + { + return author; + } + /** + * @return Returns the duration. + */ + protected String getDuration() + { + return duration; + } + /** + * @return Returns the image. + */ + protected ParsedURL getImage() + { + return image; + } + /** + * @return Returns the keywords. + */ + protected String getKeywords() + { + return keywords; + } + /** + * @return Returns the subtitle. + */ + protected String getSubtitle() + { + return subtitle; + } + /** + * @return Returns the summary. + */ + protected String getSummary() + { + return summary; + } + + /** + * Cateogory is a yuck field to define semantically, because there + * can be a single one at top level. + * There can be multiple ones at top level. + * And, additionally, they can be nested. It seems that in practice, + * their categories hierarchy only goes one deep at this time. + *

+ * Yuck! + *

+ * It seems that these are quite similar to the Category sub-element of + * media:content, except that + * 1) these can be nested + * 2) these use an attribute field named "text", instead of functioning as + * plain old leaf nodes. Triple yuck. + */ + //public Category cateogry; + + // public String explicit; + +} diff --git a/simplCore/src/ecologylab/serialization/library/itunes/package.html b/simplCore/src/ecologylab/serialization/library/itunes/package.html index 77802bf6..67007ba0 100644 --- a/simplCore/src/ecologylab/serialization/library/itunes/package.html +++ b/simplCore/src/ecologylab/serialization/library/itunes/package.html @@ -1,5 +1,5 @@ - -{@link ecologylab.xml.ElementState ElementState} - subclasses that enable translation of XML entities from the -Apple iTunes podcast namespace. - + +{@link ecologylab.xml.ElementState ElementState} + subclasses that enable translation of XML entities from the +Apple iTunes podcast namespace. + diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/AllPermissionsElement.java b/simplCore/src/ecologylab/serialization/library/jnlp/AllPermissionsElement.java index 67c6f01a..d5f094b8 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/AllPermissionsElement.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/AllPermissionsElement.java @@ -1,24 +1,24 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public @simpl_tag("all-permissions") class AllPermissionsElement extends ElementState -{ - - /** - * - */ - public AllPermissionsElement() - { - super(); - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public @simpl_tag("all-permissions") class AllPermissionsElement extends ElementState +{ + + /** + * + */ + public AllPermissionsElement() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/JnlpState.java b/simplCore/src/ecologylab/serialization/library/jnlp/JnlpState.java index 8dae92bd..00fb519c 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/JnlpState.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/JnlpState.java @@ -1,295 +1,295 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.ArrayList; - -import ecologylab.appframework.types.prefs.PrefSet; -import ecologylab.appframework.types.prefs.PrefSetBaseClassProvider; -import ecologylab.generic.Debug; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.formatenums.StringFormat; -import ecologylab.serialization.library.jnlp.applet.AppletDesc; -import ecologylab.serialization.library.jnlp.application.ApplicationDesc; -import ecologylab.serialization.library.jnlp.information.InformationElement; -import ecologylab.serialization.library.jnlp.resource.Property; -import ecologylab.serialization.library.jnlp.resource.ResourceElementArray; - -/** - * Parses JNLP files for Java web launch. - * - * Field comments from: - * - * http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/syntax.html - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class JnlpState extends ElementState implements Cloneable -{ - /** - * This attribute must be 1.0 or higher to work with this release. The default value is "1.0+". - * Thus, it can typically be omited. Note that this version supports both spec version 1.0 and - * version 1.5, whereas previous versions support only 1.0. A jnlp file specifying spec="1.5+" - * will work with this version, but not previous versions of Java Web Start. - */ - @simpl_scalar - String spec; - - /** - * All relative URLs specified in href attributes in the JNLP file are using this URL as a base. - */ - @simpl_scalar - String codebase; - - /** This is a URL pointing to the location of the JNLP file itself. */ - @simpl_scalar - String href; - - @simpl_nowrap - @simpl_collection("information") - ArrayList informations = new ArrayList(); - - // @xml_nested private InformationElement information; - - @simpl_collection("all-permissions") - ArrayList security; - - @simpl_composite - @simpl_tag("resources") - ResourceElementArray resources; - - @simpl_composite - @simpl_tag("application-desc") - ApplicationDesc applicationDesc; - - @simpl_nowrap - @simpl_collection("applet-desc") - ArrayList appletDesc = new ArrayList(); - - @simpl_nowrap - @simpl_collection("property") - ArrayList properties; - - /** - * No-arg constructor for XML translation. - */ - public JnlpState() - { - super(); - } - - /** - * @return the applet description, if any (returns null if there is not one) - */ - public AppletDesc getAppletDesc() - { - return (appletDesc == null || appletDesc.size() == 0 ? null : appletDesc.get(0)); - } - - /** - * Sets the applet description and clears the application description (since there can only be one - * or the other) and any previous applet descriptions. - * - * @param appletDesc - * the appletDesc to set - */ - public void setAppletDesc(AppletDesc appletDesc) - { - if (this.appletDesc == null) - { - this.appletDesc = new ArrayList(); - } - - this.appletDesc.clear(); - this.appletDesc.add(appletDesc); - } - - /** - * @return the application description, if any (returns null if there is not one) - */ - public ApplicationDesc getApplicationDesc() - { - return applicationDesc; - } - - /** - * Sets the application description and clears the applet description (since there can only be one - * or the other) and any previous application descriptions. - * - * @param applicationDesc - * the applicationDesc to set - */ - public void setApplicationDesc(ApplicationDesc applicationDesc) - { - this.applicationDesc = applicationDesc; - } - - /** - * @return the href - */ - public String getHref() - { - return href; - } - - /** - * @param href - * the href to set - */ - public void setHref(String href) - { - this.href = href; - } - - /** - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) - { - if (!(obj instanceof JnlpState)) - { - return false; - } - else - { - String thisXml; - try - { - thisXml = SimplTypesScope.serialize(this, StringFormat.XML).toString(); - String thatXml = SimplTypesScope.serialize(obj, StringFormat.XML).toString(); - - return thisXml.equals(thatXml); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - - return false; - } - } - } - - public static void main(String[] args) throws SIMPLTranslationException, - UnsupportedEncodingException - { - String jnlpContents = "\n" - + "\n" - + "\n" - + " \n" - + " Teaching Team Coordination through Location-Aware Games\n" - + " Interface Ecology Lab | Center for Study of Digital Libraries | Texas A&M University\n" - + " \n" - + " A multi-player team game encouraging team coordination through information differential\n" - + " A multi-player team game\n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " \n" - + " JNLP\n" - + " http://localhost:8080/rogue/lib/\n" - + " %3Cpref_set%3E%3Cpref_float+name%3D%22WALL_REPULSION%22+value%3D%221000.0%22%2F%3E%3Cpref_float+name%3D%22VALUE_IN%22+value%3D%220.1%22%2F%3E%3Cpref_int+name%3D%22INTERFACE_MODE%22+value%3D%222%22%2F%3E%3Cpref_int+name%3D%22MAX_GOALS%22+value%3D%2212%22%2F%3E%3Cpref_string+name%3D%22TUTORIAL_FILE%22+value%3D%22%2Ftutorial%2Ftutorial.xml%22%2F%3E%3Cpref_boolean+name%3D%22IS_TUTORIAL%22+value%3D%22true%22%2F%3E%3Cpref_color_mapping+name%3D%22SEEKER_COLORS%22%3E%3Cseeker_color+user_id%3D%22tests036%22%2F%3E%3C%2Fpref_color_mapping%3E%3Cpref_boolean+name%3D%22SHOW_WAP_FIELDS%22+value%3D%22true%22%2F%3E%3Cpref_string+name%3D%22APP_ID%22+value%3D%22tteclogTutorialLaunch%22%2F%3E%3Cpref_string+name%3D%22QUESTION_NAME%22+value%3D%22tutorial%22%2F%3E%3Cpref_float+name%3D%22GOAL_REPULSION%22+value%3D%2220.0%22%2F%3E%3Cpref_float+name%3D%22THREAT_KC%22+value%3D%222.5%22%2F%3E%3Cpref_int+name%3D%22debug_global_level%22+value%3D%225%22%2F%3E%3Cpref_int+name%3D%22MAX_3_GOALS%22+value%3D%223%22%2F%3E%3Cpref_int+name%3D%22log_mode%22+value%3D%224%22%2F%3E%3Cpref_int+name%3D%22MAX_CYCLES%22+value%3D%229000%22%2F%3E%3Cpref_int+name%3D%22VALUE_4_GOALS%22+value%3D%221600%22%2F%3E%3Cpref_float+name%3D%22KF%22+value%3D%220.45%22%2F%3E%3Cpref_auth_list+name%3D%22AUTH_LIST_FROM_SERVER%22%3E%3Cvalue+last_u_i_d%3D%222%22%3E%3Cauth_list%3E%3Cuser+user_key%3D%22tests036%22+password%3D%22p9RTXTHTop60vG1x5Ky5omJIoTEYMGzda7l3qSq%2BB5Q%3D%22%2F%3E%3Cuser+user_key%3D%22_coord%22+password%3D%22LPjU%2FOMOf92odzLmTRWqMpCxEE44v8xLjozoWLtTVQA%3D%22+uid%3D%221%22%2F%3E%3C%2Fauth_list%3E%3C%2Fvalue%3E%3C%2Fpref_auth_list%3E%3Cpref_int+name%3D%22logging_port%22+value%3D%2210201%22%2F%3E%3Cpref_boolean+name%3D%22SHOW_RESTORATION_ZONES%22+value%3D%22true%22%2F%3E%3Cpref_float+name%3D%22KC%22+value%3D%220.15%22%2F%3E%3Cpref_int+name%3D%22MAX_2_GOALS%22+value%3D%224%22%2F%3E%3Cpref_float+name%3D%22AVAILABLE_ACCEL%22+value%3D%221.1%22%2F%3E%3Cpref_boolean+name%3D%22SHOW_GPS_FIELDS%22+value%3D%22true%22%2F%3E%3Cpref_float+name%3D%22VIRTUAL_VISCOSITY%22+value%3D%22-0.1%22%2F%3E%3Cpref_boolean+name%3D%22SHOW_GUI%22+value%3D%22true%22%2F%3E%3Cpref_int+name%3D%22MAX_SEEKERS%22+value%3D%221%22%2F%3E%3Cpref_int+name%3D%22MAX_THREATS%22+value%3D%2220%22%2F%3E%3Cpref_int+name%3D%22PENALTY_OUT%22+value%3D%2225%22%2F%3E%3Cpref_float+name%3D%22BASE_REPULSION%22+value%3D%22100.0%22%2F%3E%3Cpref_string+name%3D%22MAP%22+value%3D%22%2Fmaps%2Ftutorial.xml%22%2F%3E%3Cpref_string+name%3D%22STUDY_PASSWORD%22+value%3D%22asdffdsa%22%2F%3E%3Cpref_int+name%3D%22MAX_COLLECT_CYCLES%22+value%3D%2215%22%2F%3E%3Cpref_float+name%3D%22THREAT_KF%22+value%3D%220.02%22%2F%3E%3Cpref_float+name%3D%22KV%22+value%3D%220.45%22%2F%3E%3Cpref_string+name%3D%22STUDY_URL%22+value%3D%22http%3A%2F%2F128.194.128.234%3A8080%2FsampleStudy%22%2F%3E%3Cpref_int+name%3D%22VALUE_1_GOALS%22+value%3D%22100%22%2F%3E%3Cpref_int+name%3D%22VALUE_2_GOALS%22+value%3D%22400%22%2F%3E%3Cpref_float+name%3D%22WORLD_VISCOSITY%22+value%3D%22-0.39999998%22%2F%3E%3Cpref_float+name%3D%22GOAL_ATTRACTION%22+value%3D%2240.0%22%2F%3E%3Cpref_int+name%3D%22VALUE_3_GOALS%22+value%3D%22900%22%2F%3E%3Cpref_boolean+name%3D%22IS_LOCATION_AWARE%22+value%3D%22true%22%2F%3E%3Cpref_float+name%3D%22THREAT_BIAS%22+value%3D%220.90000004%22%2F%3E%3Cpref_long+name%3D%22RANDOM_SEED%22+value%3D%223000%22%2F%3E%3Cpref_boolean+name%3D%22PAUSE_ON_PANIC%22%2F%3E%3Cpref_float+name%3D%22THREAT_KV%22+value%3D%220.1%22%2F%3E%3Cpref_boolean+name%3D%22SHOW_WALLS%22+value%3D%22true%22%2F%3E%3C%2Fpref_set%3E" - + " \n" + " \n" + ""; - - JnlpState j = (JnlpState) JnlpTranslations.get().deserialize(jnlpContents, StringFormat.XML); - - ArrayList infos = j.getInformations(); - for (InformationElement i : infos) - { - System.out.println("-=-=-=-"); - System.out.println(i.getTitle()); - System.out.println(i.getVendor()); - } - - ApplicationDesc appDesc = j.getApplicationDesc(); - - for (String a : appDesc.getArguments()) - { - System.out.println("arg: " + a); - } - - SimplTypesScope.serialize(j, System.out, StringFormat.XML); - - String prefSetString = URLDecoder.decode( - appDesc.getArguments().get(appDesc.getArguments().size() - 1), "UTF-8"); - SimplTypesScope[] arrayToMakeJavaShutUp = {}; - PrefSet prefs = (PrefSet) SimplTypesScope.get(PrefSet.PREFS_TRANSLATION_SCOPE, - arrayToMakeJavaShutUp, PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses()) - .deserialize(prefSetString, StringFormat.XML); - - Debug.println(prefSetString); - Debug.println(SimplTypesScope.serialize(prefs, StringFormat.XML)); - - JnlpState newState = new JnlpState(); - newState.setApplicationDesc(new ApplicationDesc()); - - newState.getApplicationDesc().setPrefSet(prefs); - - Debug.println(SimplTypesScope.serialize(newState, StringFormat.XML)); - } - - /** - * @param codebase - * the codebase to set - */ - public void setCodebase(String codebase) - { - this.codebase = codebase; - } - - /** - * @see ecologylab.serialization.types.element.ArrayListState#clone() - */ - @Override - public JnlpState clone() - { - // a bit of a hack, but it's easy! :D - try - { - return (JnlpState) JnlpTranslations.get().deserialize( - SimplTypesScope.serialize(this, StringFormat.XML), StringFormat.XML); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - - return new JnlpState(); - } - - public ArrayList getInformations() - { - return informations; - } - - @Override - public String toString() - { - return this.getHref(); - } -} +/** + * + */ +package ecologylab.serialization.library.jnlp; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.ArrayList; + +import ecologylab.appframework.types.prefs.PrefSet; +import ecologylab.appframework.types.prefs.PrefSetBaseClassProvider; +import ecologylab.generic.Debug; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.formatenums.StringFormat; +import ecologylab.serialization.library.jnlp.applet.AppletDesc; +import ecologylab.serialization.library.jnlp.application.ApplicationDesc; +import ecologylab.serialization.library.jnlp.information.InformationElement; +import ecologylab.serialization.library.jnlp.resource.Property; +import ecologylab.serialization.library.jnlp.resource.ResourceElementArray; + +/** + * Parses JNLP files for Java web launch. + * + * Field comments from: + * + * http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/syntax.html + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class JnlpState extends ElementState implements Cloneable +{ + /** + * This attribute must be 1.0 or higher to work with this release. The default value is "1.0+". + * Thus, it can typically be omited. Note that this version supports both spec version 1.0 and + * version 1.5, whereas previous versions support only 1.0. A jnlp file specifying spec="1.5+" + * will work with this version, but not previous versions of Java Web Start. + */ + @simpl_scalar + String spec; + + /** + * All relative URLs specified in href attributes in the JNLP file are using this URL as a base. + */ + @simpl_scalar + String codebase; + + /** This is a URL pointing to the location of the JNLP file itself. */ + @simpl_scalar + String href; + + @simpl_nowrap + @simpl_collection("information") + ArrayList informations = new ArrayList(); + + // @xml_nested private InformationElement information; + + @simpl_collection("all-permissions") + ArrayList security; + + @simpl_composite + @simpl_tag("resources") + ResourceElementArray resources; + + @simpl_composite + @simpl_tag("application-desc") + ApplicationDesc applicationDesc; + + @simpl_nowrap + @simpl_collection("applet-desc") + ArrayList appletDesc = new ArrayList(); + + @simpl_nowrap + @simpl_collection("property") + ArrayList properties; + + /** + * No-arg constructor for XML translation. + */ + public JnlpState() + { + super(); + } + + /** + * @return the applet description, if any (returns null if there is not one) + */ + public AppletDesc getAppletDesc() + { + return (appletDesc == null || appletDesc.size() == 0 ? null : appletDesc.get(0)); + } + + /** + * Sets the applet description and clears the application description (since there can only be one + * or the other) and any previous applet descriptions. + * + * @param appletDesc + * the appletDesc to set + */ + public void setAppletDesc(AppletDesc appletDesc) + { + if (this.appletDesc == null) + { + this.appletDesc = new ArrayList(); + } + + this.appletDesc.clear(); + this.appletDesc.add(appletDesc); + } + + /** + * @return the application description, if any (returns null if there is not one) + */ + public ApplicationDesc getApplicationDesc() + { + return applicationDesc; + } + + /** + * Sets the application description and clears the applet description (since there can only be one + * or the other) and any previous application descriptions. + * + * @param applicationDesc + * the applicationDesc to set + */ + public void setApplicationDesc(ApplicationDesc applicationDesc) + { + this.applicationDesc = applicationDesc; + } + + /** + * @return the href + */ + public String getHref() + { + return href; + } + + /** + * @param href + * the href to set + */ + public void setHref(String href) + { + this.href = href; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof JnlpState)) + { + return false; + } + else + { + String thisXml; + try + { + thisXml = SimplTypesScope.serialize(this, StringFormat.XML).toString(); + String thatXml = SimplTypesScope.serialize(obj, StringFormat.XML).toString(); + + return thisXml.equals(thatXml); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + + return false; + } + } + } + + public static void main(String[] args) throws SIMPLTranslationException, + UnsupportedEncodingException + { + String jnlpContents = "\n" + + "\n" + + "\n" + + " \n" + + " Teaching Team Coordination through Location-Aware Games\n" + + " Interface Ecology Lab | Center for Study of Digital Libraries | Texas A&M University\n" + + " \n" + + " A multi-player team game encouraging team coordination through information differential\n" + + " A multi-player team game\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " JNLP\n" + + " http://localhost:8080/rogue/lib/\n" + + " %3Cpref_set%3E%3Cpref_float+name%3D%22WALL_REPULSION%22+value%3D%221000.0%22%2F%3E%3Cpref_float+name%3D%22VALUE_IN%22+value%3D%220.1%22%2F%3E%3Cpref_int+name%3D%22INTERFACE_MODE%22+value%3D%222%22%2F%3E%3Cpref_int+name%3D%22MAX_GOALS%22+value%3D%2212%22%2F%3E%3Cpref_string+name%3D%22TUTORIAL_FILE%22+value%3D%22%2Ftutorial%2Ftutorial.xml%22%2F%3E%3Cpref_boolean+name%3D%22IS_TUTORIAL%22+value%3D%22true%22%2F%3E%3Cpref_color_mapping+name%3D%22SEEKER_COLORS%22%3E%3Cseeker_color+user_id%3D%22tests036%22%2F%3E%3C%2Fpref_color_mapping%3E%3Cpref_boolean+name%3D%22SHOW_WAP_FIELDS%22+value%3D%22true%22%2F%3E%3Cpref_string+name%3D%22APP_ID%22+value%3D%22tteclogTutorialLaunch%22%2F%3E%3Cpref_string+name%3D%22QUESTION_NAME%22+value%3D%22tutorial%22%2F%3E%3Cpref_float+name%3D%22GOAL_REPULSION%22+value%3D%2220.0%22%2F%3E%3Cpref_float+name%3D%22THREAT_KC%22+value%3D%222.5%22%2F%3E%3Cpref_int+name%3D%22debug_global_level%22+value%3D%225%22%2F%3E%3Cpref_int+name%3D%22MAX_3_GOALS%22+value%3D%223%22%2F%3E%3Cpref_int+name%3D%22log_mode%22+value%3D%224%22%2F%3E%3Cpref_int+name%3D%22MAX_CYCLES%22+value%3D%229000%22%2F%3E%3Cpref_int+name%3D%22VALUE_4_GOALS%22+value%3D%221600%22%2F%3E%3Cpref_float+name%3D%22KF%22+value%3D%220.45%22%2F%3E%3Cpref_auth_list+name%3D%22AUTH_LIST_FROM_SERVER%22%3E%3Cvalue+last_u_i_d%3D%222%22%3E%3Cauth_list%3E%3Cuser+user_key%3D%22tests036%22+password%3D%22p9RTXTHTop60vG1x5Ky5omJIoTEYMGzda7l3qSq%2BB5Q%3D%22%2F%3E%3Cuser+user_key%3D%22_coord%22+password%3D%22LPjU%2FOMOf92odzLmTRWqMpCxEE44v8xLjozoWLtTVQA%3D%22+uid%3D%221%22%2F%3E%3C%2Fauth_list%3E%3C%2Fvalue%3E%3C%2Fpref_auth_list%3E%3Cpref_int+name%3D%22logging_port%22+value%3D%2210201%22%2F%3E%3Cpref_boolean+name%3D%22SHOW_RESTORATION_ZONES%22+value%3D%22true%22%2F%3E%3Cpref_float+name%3D%22KC%22+value%3D%220.15%22%2F%3E%3Cpref_int+name%3D%22MAX_2_GOALS%22+value%3D%224%22%2F%3E%3Cpref_float+name%3D%22AVAILABLE_ACCEL%22+value%3D%221.1%22%2F%3E%3Cpref_boolean+name%3D%22SHOW_GPS_FIELDS%22+value%3D%22true%22%2F%3E%3Cpref_float+name%3D%22VIRTUAL_VISCOSITY%22+value%3D%22-0.1%22%2F%3E%3Cpref_boolean+name%3D%22SHOW_GUI%22+value%3D%22true%22%2F%3E%3Cpref_int+name%3D%22MAX_SEEKERS%22+value%3D%221%22%2F%3E%3Cpref_int+name%3D%22MAX_THREATS%22+value%3D%2220%22%2F%3E%3Cpref_int+name%3D%22PENALTY_OUT%22+value%3D%2225%22%2F%3E%3Cpref_float+name%3D%22BASE_REPULSION%22+value%3D%22100.0%22%2F%3E%3Cpref_string+name%3D%22MAP%22+value%3D%22%2Fmaps%2Ftutorial.xml%22%2F%3E%3Cpref_string+name%3D%22STUDY_PASSWORD%22+value%3D%22asdffdsa%22%2F%3E%3Cpref_int+name%3D%22MAX_COLLECT_CYCLES%22+value%3D%2215%22%2F%3E%3Cpref_float+name%3D%22THREAT_KF%22+value%3D%220.02%22%2F%3E%3Cpref_float+name%3D%22KV%22+value%3D%220.45%22%2F%3E%3Cpref_string+name%3D%22STUDY_URL%22+value%3D%22http%3A%2F%2F128.194.128.234%3A8080%2FsampleStudy%22%2F%3E%3Cpref_int+name%3D%22VALUE_1_GOALS%22+value%3D%22100%22%2F%3E%3Cpref_int+name%3D%22VALUE_2_GOALS%22+value%3D%22400%22%2F%3E%3Cpref_float+name%3D%22WORLD_VISCOSITY%22+value%3D%22-0.39999998%22%2F%3E%3Cpref_float+name%3D%22GOAL_ATTRACTION%22+value%3D%2240.0%22%2F%3E%3Cpref_int+name%3D%22VALUE_3_GOALS%22+value%3D%22900%22%2F%3E%3Cpref_boolean+name%3D%22IS_LOCATION_AWARE%22+value%3D%22true%22%2F%3E%3Cpref_float+name%3D%22THREAT_BIAS%22+value%3D%220.90000004%22%2F%3E%3Cpref_long+name%3D%22RANDOM_SEED%22+value%3D%223000%22%2F%3E%3Cpref_boolean+name%3D%22PAUSE_ON_PANIC%22%2F%3E%3Cpref_float+name%3D%22THREAT_KV%22+value%3D%220.1%22%2F%3E%3Cpref_boolean+name%3D%22SHOW_WALLS%22+value%3D%22true%22%2F%3E%3C%2Fpref_set%3E" + + " \n" + " \n" + ""; + + JnlpState j = (JnlpState) JnlpTranslations.get().deserialize(jnlpContents, StringFormat.XML); + + ArrayList infos = j.getInformations(); + for (InformationElement i : infos) + { + System.out.println("-=-=-=-"); + System.out.println(i.getTitle()); + System.out.println(i.getVendor()); + } + + ApplicationDesc appDesc = j.getApplicationDesc(); + + for (String a : appDesc.getArguments()) + { + System.out.println("arg: " + a); + } + + SimplTypesScope.serialize(j, System.out, StringFormat.XML); + + String prefSetString = URLDecoder.decode( + appDesc.getArguments().get(appDesc.getArguments().size() - 1), "UTF-8"); + SimplTypesScope[] arrayToMakeJavaShutUp = {}; + PrefSet prefs = (PrefSet) SimplTypesScope.get(PrefSet.PREFS_TRANSLATION_SCOPE, + arrayToMakeJavaShutUp, PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses()) + .deserialize(prefSetString, StringFormat.XML); + + Debug.println(prefSetString); + Debug.println(SimplTypesScope.serialize(prefs, StringFormat.XML)); + + JnlpState newState = new JnlpState(); + newState.setApplicationDesc(new ApplicationDesc()); + + newState.getApplicationDesc().setPrefSet(prefs); + + Debug.println(SimplTypesScope.serialize(newState, StringFormat.XML)); + } + + /** + * @param codebase + * the codebase to set + */ + public void setCodebase(String codebase) + { + this.codebase = codebase; + } + + /** + * @see ecologylab.serialization.types.element.ArrayListState#clone() + */ + @Override + public JnlpState clone() + { + // a bit of a hack, but it's easy! :D + try + { + return (JnlpState) JnlpTranslations.get().deserialize( + SimplTypesScope.serialize(this, StringFormat.XML), StringFormat.XML); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + + return new JnlpState(); + } + + public ArrayList getInformations() + { + return informations; + } + + @Override + public String toString() + { + return this.getHref(); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/JnlpTranslations.java b/simplCore/src/ecologylab/serialization/library/jnlp/JnlpTranslations.java index 07a43fe8..5bb1892c 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/JnlpTranslations.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/JnlpTranslations.java @@ -1,78 +1,78 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp; - -import ecologylab.appframework.types.AppFrameworkTranslations; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.library.jnlp.applet.AppletDesc; -import ecologylab.serialization.library.jnlp.applet.Param; -import ecologylab.serialization.library.jnlp.application.ApplicationDesc; -import ecologylab.serialization.library.jnlp.information.AssociationElement; -import ecologylab.serialization.library.jnlp.information.Description; -import ecologylab.serialization.library.jnlp.information.HomepageElement; -import ecologylab.serialization.library.jnlp.information.Icon; -import ecologylab.serialization.library.jnlp.information.InformationElement; -import ecologylab.serialization.library.jnlp.information.MenuElement; -import ecologylab.serialization.library.jnlp.information.OfflineAllowedElement; -import ecologylab.serialization.library.jnlp.information.RelatedContentElement; -import ecologylab.serialization.library.jnlp.information.ShortcutElement; -import ecologylab.serialization.library.jnlp.resource.HrefBasedResource; -import ecologylab.serialization.library.jnlp.resource.J2se; -import ecologylab.serialization.library.jnlp.resource.Jar; -import ecologylab.serialization.library.jnlp.resource.Nativelib; -import ecologylab.serialization.library.jnlp.resource.Property; -import ecologylab.serialization.library.jnlp.resource.ResourceElement; -import ecologylab.serialization.library.jnlp.resource.ResourceElementArray; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class JnlpTranslations -{ - private static final String JNLP_TRANSLATIONS_NAME = "JNLP Translations"; - - private static final Class[] JNLP_TRANSLATIONS = - { - AppletDesc.class, Param.class, - - ApplicationDesc.class, - - AssociationElement.class, Description.class, HomepageElement.class, - Icon.class, InformationElement.class, MenuElement.class, - RelatedContentElement.class, ShortcutElement.class, - OfflineAllowedElement.class, - - AllPermissionsElement.class, HrefBasedResource.class, J2se.class, - Jar.class, Nativelib.class, Property.class, ResourceElement.class, - ResourceElementArray.class, JnlpState.class }; - - private static final SimplTypesScope inheritedTranslations[] = - { - AppFrameworkTranslations.get(), - JnlpTranslations.getStudyTranslationsOnly() }; - - /** - * This accessor will work from anywhere, in any order, and stay efficient. - * - * @return - */ - public static SimplTypesScope get() - { - SimplTypesScope result = SimplTypesScope.get(JNLP_TRANSLATIONS_NAME, - inheritedTranslations, JNLP_TRANSLATIONS); - - return result; - } - - /** - * @return - */ - private static SimplTypesScope getStudyTranslationsOnly() - { - SimplTypesScope temp = SimplTypesScope.get(JNLP_TRANSLATIONS_NAME, JNLP_TRANSLATIONS); - - return temp; - } -} +/** + * + */ +package ecologylab.serialization.library.jnlp; + +import ecologylab.appframework.types.AppFrameworkTranslations; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.library.jnlp.applet.AppletDesc; +import ecologylab.serialization.library.jnlp.applet.Param; +import ecologylab.serialization.library.jnlp.application.ApplicationDesc; +import ecologylab.serialization.library.jnlp.information.AssociationElement; +import ecologylab.serialization.library.jnlp.information.Description; +import ecologylab.serialization.library.jnlp.information.HomepageElement; +import ecologylab.serialization.library.jnlp.information.Icon; +import ecologylab.serialization.library.jnlp.information.InformationElement; +import ecologylab.serialization.library.jnlp.information.MenuElement; +import ecologylab.serialization.library.jnlp.information.OfflineAllowedElement; +import ecologylab.serialization.library.jnlp.information.RelatedContentElement; +import ecologylab.serialization.library.jnlp.information.ShortcutElement; +import ecologylab.serialization.library.jnlp.resource.HrefBasedResource; +import ecologylab.serialization.library.jnlp.resource.J2se; +import ecologylab.serialization.library.jnlp.resource.Jar; +import ecologylab.serialization.library.jnlp.resource.Nativelib; +import ecologylab.serialization.library.jnlp.resource.Property; +import ecologylab.serialization.library.jnlp.resource.ResourceElement; +import ecologylab.serialization.library.jnlp.resource.ResourceElementArray; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class JnlpTranslations +{ + private static final String JNLP_TRANSLATIONS_NAME = "JNLP Translations"; + + private static final Class[] JNLP_TRANSLATIONS = + { + AppletDesc.class, Param.class, + + ApplicationDesc.class, + + AssociationElement.class, Description.class, HomepageElement.class, + Icon.class, InformationElement.class, MenuElement.class, + RelatedContentElement.class, ShortcutElement.class, + OfflineAllowedElement.class, + + AllPermissionsElement.class, HrefBasedResource.class, J2se.class, + Jar.class, Nativelib.class, Property.class, ResourceElement.class, + ResourceElementArray.class, JnlpState.class }; + + private static final SimplTypesScope inheritedTranslations[] = + { + AppFrameworkTranslations.get(), + JnlpTranslations.getStudyTranslationsOnly() }; + + /** + * This accessor will work from anywhere, in any order, and stay efficient. + * + * @return + */ + public static SimplTypesScope get() + { + SimplTypesScope result = SimplTypesScope.get(JNLP_TRANSLATIONS_NAME, + inheritedTranslations, JNLP_TRANSLATIONS); + + return result; + } + + /** + * @return + */ + private static SimplTypesScope getStudyTranslationsOnly() + { + SimplTypesScope temp = SimplTypesScope.get(JNLP_TRANSLATIONS_NAME, JNLP_TRANSLATIONS); + + return temp; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/applet/AppletDesc.java b/simplCore/src/ecologylab/serialization/library/jnlp/applet/AppletDesc.java index 0cc9dfd8..e6e91cd0 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/applet/AppletDesc.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/applet/AppletDesc.java @@ -1,48 +1,48 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.applet; - -import java.util.ArrayList; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class AppletDesc extends ElementState -{ - @simpl_scalar - private String documentBase; - - @simpl_scalar - private String name; - - @simpl_scalar - @simpl_tag("main-class") - private String mainClass; - - @simpl_scalar - private int width; - - @simpl_scalar - private int height; - - @simpl_nowrap - @simpl_collection("Param") - ArrayList params; - - /** - * - */ - public AppletDesc() - { - super(); - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.applet; + +import java.util.ArrayList; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class AppletDesc extends ElementState +{ + @simpl_scalar + private String documentBase; + + @simpl_scalar + private String name; + + @simpl_scalar + @simpl_tag("main-class") + private String mainClass; + + @simpl_scalar + private int width; + + @simpl_scalar + private int height; + + @simpl_nowrap + @simpl_collection("Param") + ArrayList params; + + /** + * + */ + public AppletDesc() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/applet/Param.java b/simplCore/src/ecologylab/serialization/library/jnlp/applet/Param.java index cca67052..e47bce35 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/applet/Param.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/applet/Param.java @@ -1,26 +1,26 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.applet; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class Param extends ElementState -{ - @simpl_scalar private String name; - @simpl_scalar private String value; - - /** - * - */ - public Param() - { - super(); - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.applet; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class Param extends ElementState +{ + @simpl_scalar private String name; + @simpl_scalar private String value; + + /** + * + */ + public Param() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/application/ApplicationDesc.java b/simplCore/src/ecologylab/serialization/library/jnlp/application/ApplicationDesc.java index 51d6ae3d..232af967 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/application/ApplicationDesc.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/application/ApplicationDesc.java @@ -1,129 +1,129 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.application; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.ArrayList; - -import ecologylab.appframework.types.prefs.PrefSet; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class ApplicationDesc extends ElementState -{ - @simpl_scalar - @simpl_tag("main-class") - String mainClass; - - @simpl_nowrap - @simpl_collection("argument") - ArrayList arguments = new ArrayList(); - - /** - * The PrefSet that is to be passed as an argument through the JNLP file. This object is - * serialized separately and added to the list of arguments at serialization time. After the JNLP - * file has been serialized, it is removed from the arguments. It may be safely modified between - * serializations to provide different sets of prefs. - */ - private PrefSet prefSet; - - private int prefSetArgumentIndex = -1; - - /** - * - */ - public ApplicationDesc() - { - super(); - } - - /** - * Add the argument to the JNLP application description. - * - * @param argument - */ - public void add(String argument) - { - this.arguments.add(argument); - } - - public ArrayList getArguments() - { - return arguments; - } - - /** - * @return the prefSet - */ - public PrefSet getPrefSet() - { - return prefSet; - } - - /** - * @param prefSet - * the prefSet to set - */ - public void setPrefSet(PrefSet prefSet) - { - this.prefSet = prefSet; - } - - /** - * @see ecologylab.serialization.ElementState#serializationPreHook() - */ - @Override - public void serializationPreHook(TranslationContext translationContext) - { - if (prefSet != null) - { - try - { - - this.add(URLEncoder.encode(SimplTypesScope.serialize(prefSet, StringFormat.XML).toString(), - "UTF-8")); - - this.prefSetArgumentIndex = this.arguments.size() - 1; - } - catch (UnsupportedEncodingException e) - { - e.printStackTrace(); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - } - - super.serializationPreHook(translationContext); - } - - /** - * @see ecologylab.serialization.ElementState#serializationPostHook() - */ - @Override - public void serializationPostHook(TranslationContext translationContext) - { - if (this.prefSetArgumentIndex > -1) - { // we need to remove it from the arguments list - this.arguments.remove(this.prefSetArgumentIndex); - - this.prefSetArgumentIndex = -1; - } - - super.serializationPostHook(translationContext); - } -} +/** + * + */ +package ecologylab.serialization.library.jnlp.application; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.ArrayList; + +import ecologylab.appframework.types.prefs.PrefSet; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class ApplicationDesc extends ElementState +{ + @simpl_scalar + @simpl_tag("main-class") + String mainClass; + + @simpl_nowrap + @simpl_collection("argument") + ArrayList arguments = new ArrayList(); + + /** + * The PrefSet that is to be passed as an argument through the JNLP file. This object is + * serialized separately and added to the list of arguments at serialization time. After the JNLP + * file has been serialized, it is removed from the arguments. It may be safely modified between + * serializations to provide different sets of prefs. + */ + private PrefSet prefSet; + + private int prefSetArgumentIndex = -1; + + /** + * + */ + public ApplicationDesc() + { + super(); + } + + /** + * Add the argument to the JNLP application description. + * + * @param argument + */ + public void add(String argument) + { + this.arguments.add(argument); + } + + public ArrayList getArguments() + { + return arguments; + } + + /** + * @return the prefSet + */ + public PrefSet getPrefSet() + { + return prefSet; + } + + /** + * @param prefSet + * the prefSet to set + */ + public void setPrefSet(PrefSet prefSet) + { + this.prefSet = prefSet; + } + + /** + * @see ecologylab.serialization.ElementState#serializationPreHook() + */ + @Override + public void serializationPreHook(TranslationContext translationContext) + { + if (prefSet != null) + { + try + { + + this.add(URLEncoder.encode(SimplTypesScope.serialize(prefSet, StringFormat.XML).toString(), + "UTF-8")); + + this.prefSetArgumentIndex = this.arguments.size() - 1; + } + catch (UnsupportedEncodingException e) + { + e.printStackTrace(); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + } + + super.serializationPreHook(translationContext); + } + + /** + * @see ecologylab.serialization.ElementState#serializationPostHook() + */ + @Override + public void serializationPostHook(TranslationContext translationContext) + { + if (this.prefSetArgumentIndex > -1) + { // we need to remove it from the arguments list + this.arguments.remove(this.prefSetArgumentIndex); + + this.prefSetArgumentIndex = -1; + } + + super.serializationPostHook(translationContext); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/information/AssociationElement.java b/simplCore/src/ecologylab/serialization/library/jnlp/information/AssociationElement.java index 32320f47..2a063e0d 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/information/AssociationElement.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/information/AssociationElement.java @@ -1,28 +1,28 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.information; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class AssociationElement extends ElementState -{ - @simpl_scalar @simpl_tag("mime-type") private String mimeType; - - @simpl_scalar private String extensions; - - /** - * - */ - public AssociationElement() - { - super(); - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.information; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class AssociationElement extends ElementState +{ + @simpl_scalar @simpl_tag("mime-type") private String mimeType; + + @simpl_scalar private String extensions; + + /** + * + */ + public AssociationElement() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/information/Description.java b/simplCore/src/ecologylab/serialization/library/jnlp/information/Description.java index 05ccfc08..c0e48170 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/information/Description.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/information/Description.java @@ -1,63 +1,63 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.information; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.element.IMappable; - -/** - * A short statement about the application. Description elements are optional. The kind attribute defines how the - * description should be used. It can have one of the following values: - * - *

    - *
  • one-line: If a reference to the application is going to appear on one row in a list or a table, this description - * will be used.
  • - *
  • short: If a reference to the application is going to be displayed in a situation where there is room for a - * paragraph, this description is used.
  • - *
  • tooltip: If a reference to the application is going to appear in a tooltip, this description is used.
  • - *
- * - * Only one description element of each kind can be specified. A description element without a kind is used as a default - * value. Thus, if Java Web Start needs a description of kind short, and it is not specified in the JNLP file, then the - * text from the description without an attribute is used. - * - * All descriptions contain plain text. No formatting, such as with HTML tags, is supported. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public class Description extends ElementState implements IMappable -{ - @simpl_scalar private String kind; - - @simpl_scalar @simpl_hints(Hint.XML_TEXT) private String desc; - - /** - * - */ - public Description() - { - super(); - } - - /** - * @see ecologylab.serialization.types.element.IMappable#key() - */ - @Override - public String key() - { - return desc; - } - - /** - * @return the desc - */ - public String getDesc() - { - return desc; - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.information; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.element.IMappable; + +/** + * A short statement about the application. Description elements are optional. The kind attribute defines how the + * description should be used. It can have one of the following values: + * + *
    + *
  • one-line: If a reference to the application is going to appear on one row in a list or a table, this description + * will be used.
  • + *
  • short: If a reference to the application is going to be displayed in a situation where there is room for a + * paragraph, this description is used.
  • + *
  • tooltip: If a reference to the application is going to appear in a tooltip, this description is used.
  • + *
+ * + * Only one description element of each kind can be specified. A description element without a kind is used as a default + * value. Thus, if Java Web Start needs a description of kind short, and it is not specified in the JNLP file, then the + * text from the description without an attribute is used. + * + * All descriptions contain plain text. No formatting, such as with HTML tags, is supported. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public class Description extends ElementState implements IMappable +{ + @simpl_scalar private String kind; + + @simpl_scalar @simpl_hints(Hint.XML_TEXT) private String desc; + + /** + * + */ + public Description() + { + super(); + } + + /** + * @see ecologylab.serialization.types.element.IMappable#key() + */ + @Override + public String key() + { + return desc; + } + + /** + * @return the desc + */ + public String getDesc() + { + return desc; + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/information/HomepageElement.java b/simplCore/src/ecologylab/serialization/library/jnlp/information/HomepageElement.java index b9bb9e86..d69b1b16 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/information/HomepageElement.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/information/HomepageElement.java @@ -1,28 +1,28 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.information; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Contains a single attribute, href, which is a URL locating the home page for the Application. It is used by the Java - * Application Cache Viewer to point the user to a Web page where more information about the application can be found. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class HomepageElement extends ElementState -{ - private @simpl_scalar String href; - - /** - * - */ - public HomepageElement() - { - super(); - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.information; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Contains a single attribute, href, which is a URL locating the home page for the Application. It is used by the Java + * Application Cache Viewer to point the user to a Web page where more information about the application can be found. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class HomepageElement extends ElementState +{ + private @simpl_scalar String href; + + /** + * + */ + public HomepageElement() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/information/Icon.java b/simplCore/src/ecologylab/serialization/library/jnlp/information/Icon.java index 6449787c..1eaae863 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/information/Icon.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/information/Icon.java @@ -1,58 +1,58 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.information; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Contains an HTTP URL to an image file in either GIF or JPEG format. The icons are used to represents the application - * - *
    - *
  • during launch when Java Web Start presents the application to the user;
  • - *
  • in the Java Application Cache Viewer;
  • - *
  • in desktop shortcuts.
  • - *
- * - * A 64x64 icon is shown during download; in the Java Application Cache Viewer and in desktop shortcuts a 32x32 icon is - * used. Java Web Start automatically resizes an icon to the appropriate size. - * - * The icon element requires an href attribute, specifiying the directory and name of the icon file. - * - * Optional width and height attributes can be used to indicate the size of the images. - * - * The optional kind="splash" attribute may be used in an icon element to indicate that the image is to be used as a - * "splash" screen during the launch of an application. If the JNLP file does not contain an icon element with - * kind="splash" attribute, Java Web Start will construct a splash screen using other items from the information - * Element. - * - * If the JNLP file does not contain any icon images, the splash image will consist of the application's title and - * vendor, as taken from the JNLP file. - * - * The first time an application is launched following the addition or modification of the icon element in the JNLP - * file, the old splash image will still be displayed. The new splash image will appear on the second and subsequent - * launches of the application. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class Icon extends ElementState -{ - @simpl_scalar private String href; - - @simpl_scalar private int width; - - @simpl_scalar private int height; - - @simpl_scalar private String kind; - - /** - * - */ - public Icon() - { - super(); - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.information; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Contains an HTTP URL to an image file in either GIF or JPEG format. The icons are used to represents the application + * + *
    + *
  • during launch when Java Web Start presents the application to the user;
  • + *
  • in the Java Application Cache Viewer;
  • + *
  • in desktop shortcuts.
  • + *
+ * + * A 64x64 icon is shown during download; in the Java Application Cache Viewer and in desktop shortcuts a 32x32 icon is + * used. Java Web Start automatically resizes an icon to the appropriate size. + * + * The icon element requires an href attribute, specifiying the directory and name of the icon file. + * + * Optional width and height attributes can be used to indicate the size of the images. + * + * The optional kind="splash" attribute may be used in an icon element to indicate that the image is to be used as a + * "splash" screen during the launch of an application. If the JNLP file does not contain an icon element with + * kind="splash" attribute, Java Web Start will construct a splash screen using other items from the information + * Element. + * + * If the JNLP file does not contain any icon images, the splash image will consist of the application's title and + * vendor, as taken from the JNLP file. + * + * The first time an application is launched following the addition or modification of the icon element in the JNLP + * file, the old splash image will still be displayed. The new splash image will appear on the second and subsequent + * launches of the application. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class Icon extends ElementState +{ + @simpl_scalar private String href; + + @simpl_scalar private int width; + + @simpl_scalar private int height; + + @simpl_scalar private String kind; + + /** + * + */ + public Icon() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/information/InformationElement.java b/simplCore/src/ecologylab/serialization/library/jnlp/information/InformationElement.java index 3e900355..44cfa5b2 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/information/InformationElement.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/information/InformationElement.java @@ -1,173 +1,173 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.information; - -import java.util.ArrayList; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public @simpl_inherit @simpl_tag("information") class InformationElement extends ElementState -{ - @simpl_scalar protected String os; - - /** The name of the application. This element is required. */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String title; - - /** The name of the vendor of the application. This element is required. */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String vendor; - - /** - * Contains a single attribute, href, which is a URL locating the home page for the Application. It is used by the - * Java Application Cache Viewer to point the user to a Web page where more information about the application can be - * found. - */ - @simpl_composite protected HomepageElement homepage; - - /** - * A short statement about the application. Description elements are optional. The kind attribute defines how the - * description should be used. It can have one of the following values: - * - *
    - *
  • one-line: If a reference to the application is going to appear on one row in a list or a table, this - * description will be used.
  • - *
  • short: If a reference to the application is going to be displayed in a situation where there is room for a - * paragraph, this description is used.
  • - *
  • tooltip: If a reference to the application is going to appear in a tooltip, this description is used.
  • - *
- * - * Only one description element of each kind can be specified. A description element without a kind is used as a - * default value. Thus, if Java Web Start needs a description of kind short, and it is not specified in the JNLP - * file, then the text from the description without an attribute is used. - * - * All descriptions contain plain text. No formatting, such as with HTML tags, is supported. - */ - @simpl_nowrap - @simpl_collection("description") protected ArrayList descriptions = new ArrayList(); - - /** - * Contains an HTTP URL to an image file in either GIF or JPEG format. The icons are used to represents the - * application - * - *
    - *
  • during launch when Java Web Start presents the application to the user;
  • - *
  • in the Java Application Cache Viewer;
  • - *
  • in desktop shortcuts.
  • - *
- * - * A 64x64 icon is shown during download; in the Java Application Cache Viewer and in desktop shortcuts a 32x32 icon - * is used. Java Web Start automatically resizes an icon to the appropriate size. - * - * The icon element requires an href attribute, specifiying the directory and name of the icon file. - * - * Optional width and height attributes can be used to indicate the size of the images. - * - * The optional kind="splash" attribute may be used in an icon element to indicate that the image is to be used as a - * "splash" screen during the launch of an application. If the JNLP file does not contain an icon element with - * kind="splash" attribute, Java Web Start will construct a splash screen using other items from the information - * Element. - * - * If the JNLP file does not contain any icon images, the splash image will consist of the application's title and - * vendor, as taken from the JNLP file. - * - * The first time an application is launched following the addition or modification of the icon element in the JNLP - * file, the old splash image will still be displayed. The new splash image will appear on the second and subsequent - * launches of the application. - */ - @simpl_nowrap - @simpl_collection("icon") protected ArrayList icons = new ArrayList(); - - /** - * offline-allowed element: The optional offline-allowed element indicates if the application can be launched - * offline. - * - * If offline-allowed is specified, then the application can be launched offline by the Java Application Cache - * Viewer, and shortcuts can be created which launch the application offline. - * - * If an application is launched offline, it will not check for updates and the API call BasicService.isOffline() - * will return true. - * - * The offline-allowed element also controls how Java Web Start checks for an update to an application. If the - * element is not specified i.e., the application is required to be online to run Java Web Start will always check - * for an updated version before launching the application. And if an update is found, the new application will be - * downloaded and launched. Thus, it is guaranteed that the user always runs the latest version of the application. - * The application, however, must be run online. - * - * If offline-allowed is specified, Java Web Start will also check to see if an update is available. However, if the - * application is already downloaded the check will timeout after a few seconds, in which case the cached - * application will be launched instead. Given a reasonably fast server connection, the latest version of the - * application will usually be run, but it is not guaranteed. The application, however, can be run offline. - */ - @simpl_nowrap - @simpl_collection("offline-allowed") protected ArrayList offlineAllowed = new ArrayList(); - - /** - * The optional association element is a hint to the JNLP client that it wishes to be registered with the operating - * system as the primary handler of certain extensions and a certain mime-type. The association element must have - * the extensions and mime-type attributes. - */ - @simpl_composite protected AssociationElement association; - - /** - * shortcut element: The optional shortcut element can be used to indicate an application's preferences for desktop - * integration. The shortcut element and it's sub-elements provide hints that the JNLP Client may or may not use. - * The shortcut element can contain the optional online attribute, and the two optional sub-elements, desktop and - * menu. - */ - @simpl_composite protected ShortcutElement shortcut; - - /** - * related-content element: The optional related-content element describes an additional piece of related content, - * such as a readme file, help pages, or links to registration pages, as a hint to a JNLP Client. The application is - * asking that this content be included in its desktop integration. The related-content element has a mandatory href - * and title attribute. It can contain any of the following two sub-elements: - * - * description element: A short description of the related content. icon element: The icon can be used by the JNLP - * Client to identify the related content to the user. - */ - @simpl_composite @simpl_tag("related-content") RelatedContentElement relatedContent; - - /** No-argument constructor for XML translation. */ - public InformationElement() - { - super(); - } - - /** - * @return the descriptions - */ - public ArrayList getDescriptions() - { - return descriptions; - } - - /** - * @return the icons - */ - public ArrayList getIcons() - { - return icons; - } - - public String getTitle() - { - return title; - } - - public String getVendor() - { - return vendor; - } -} +/** + * + */ +package ecologylab.serialization.library.jnlp.information; + +import java.util.ArrayList; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public @simpl_inherit @simpl_tag("information") class InformationElement extends ElementState +{ + @simpl_scalar protected String os; + + /** The name of the application. This element is required. */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String title; + + /** The name of the vendor of the application. This element is required. */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String vendor; + + /** + * Contains a single attribute, href, which is a URL locating the home page for the Application. It is used by the + * Java Application Cache Viewer to point the user to a Web page where more information about the application can be + * found. + */ + @simpl_composite protected HomepageElement homepage; + + /** + * A short statement about the application. Description elements are optional. The kind attribute defines how the + * description should be used. It can have one of the following values: + * + *
    + *
  • one-line: If a reference to the application is going to appear on one row in a list or a table, this + * description will be used.
  • + *
  • short: If a reference to the application is going to be displayed in a situation where there is room for a + * paragraph, this description is used.
  • + *
  • tooltip: If a reference to the application is going to appear in a tooltip, this description is used.
  • + *
+ * + * Only one description element of each kind can be specified. A description element without a kind is used as a + * default value. Thus, if Java Web Start needs a description of kind short, and it is not specified in the JNLP + * file, then the text from the description without an attribute is used. + * + * All descriptions contain plain text. No formatting, such as with HTML tags, is supported. + */ + @simpl_nowrap + @simpl_collection("description") protected ArrayList descriptions = new ArrayList(); + + /** + * Contains an HTTP URL to an image file in either GIF or JPEG format. The icons are used to represents the + * application + * + *
    + *
  • during launch when Java Web Start presents the application to the user;
  • + *
  • in the Java Application Cache Viewer;
  • + *
  • in desktop shortcuts.
  • + *
+ * + * A 64x64 icon is shown during download; in the Java Application Cache Viewer and in desktop shortcuts a 32x32 icon + * is used. Java Web Start automatically resizes an icon to the appropriate size. + * + * The icon element requires an href attribute, specifiying the directory and name of the icon file. + * + * Optional width and height attributes can be used to indicate the size of the images. + * + * The optional kind="splash" attribute may be used in an icon element to indicate that the image is to be used as a + * "splash" screen during the launch of an application. If the JNLP file does not contain an icon element with + * kind="splash" attribute, Java Web Start will construct a splash screen using other items from the information + * Element. + * + * If the JNLP file does not contain any icon images, the splash image will consist of the application's title and + * vendor, as taken from the JNLP file. + * + * The first time an application is launched following the addition or modification of the icon element in the JNLP + * file, the old splash image will still be displayed. The new splash image will appear on the second and subsequent + * launches of the application. + */ + @simpl_nowrap + @simpl_collection("icon") protected ArrayList icons = new ArrayList(); + + /** + * offline-allowed element: The optional offline-allowed element indicates if the application can be launched + * offline. + * + * If offline-allowed is specified, then the application can be launched offline by the Java Application Cache + * Viewer, and shortcuts can be created which launch the application offline. + * + * If an application is launched offline, it will not check for updates and the API call BasicService.isOffline() + * will return true. + * + * The offline-allowed element also controls how Java Web Start checks for an update to an application. If the + * element is not specified i.e., the application is required to be online to run Java Web Start will always check + * for an updated version before launching the application. And if an update is found, the new application will be + * downloaded and launched. Thus, it is guaranteed that the user always runs the latest version of the application. + * The application, however, must be run online. + * + * If offline-allowed is specified, Java Web Start will also check to see if an update is available. However, if the + * application is already downloaded the check will timeout after a few seconds, in which case the cached + * application will be launched instead. Given a reasonably fast server connection, the latest version of the + * application will usually be run, but it is not guaranteed. The application, however, can be run offline. + */ + @simpl_nowrap + @simpl_collection("offline-allowed") protected ArrayList offlineAllowed = new ArrayList(); + + /** + * The optional association element is a hint to the JNLP client that it wishes to be registered with the operating + * system as the primary handler of certain extensions and a certain mime-type. The association element must have + * the extensions and mime-type attributes. + */ + @simpl_composite protected AssociationElement association; + + /** + * shortcut element: The optional shortcut element can be used to indicate an application's preferences for desktop + * integration. The shortcut element and it's sub-elements provide hints that the JNLP Client may or may not use. + * The shortcut element can contain the optional online attribute, and the two optional sub-elements, desktop and + * menu. + */ + @simpl_composite protected ShortcutElement shortcut; + + /** + * related-content element: The optional related-content element describes an additional piece of related content, + * such as a readme file, help pages, or links to registration pages, as a hint to a JNLP Client. The application is + * asking that this content be included in its desktop integration. The related-content element has a mandatory href + * and title attribute. It can contain any of the following two sub-elements: + * + * description element: A short description of the related content. icon element: The icon can be used by the JNLP + * Client to identify the related content to the user. + */ + @simpl_composite @simpl_tag("related-content") RelatedContentElement relatedContent; + + /** No-argument constructor for XML translation. */ + public InformationElement() + { + super(); + } + + /** + * @return the descriptions + */ + public ArrayList getDescriptions() + { + return descriptions; + } + + /** + * @return the icons + */ + public ArrayList getIcons() + { + return icons; + } + + public String getTitle() + { + return title; + } + + public String getVendor() + { + return vendor; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/information/MenuElement.java b/simplCore/src/ecologylab/serialization/library/jnlp/information/MenuElement.java index f760d802..e3e3bb13 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/information/MenuElement.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/information/MenuElement.java @@ -1,24 +1,24 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.information; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class MenuElement extends ElementState -{ - @simpl_scalar private String submenu; - - /** - * - */ - public MenuElement() - { - super(); - } -} +/** + * + */ +package ecologylab.serialization.library.jnlp.information; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class MenuElement extends ElementState +{ + @simpl_scalar private String submenu; + + /** + * + */ + public MenuElement() + { + super(); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/information/OfflineAllowedElement.java b/simplCore/src/ecologylab/serialization/library/jnlp/information/OfflineAllowedElement.java index bd4f80d1..501472c1 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/information/OfflineAllowedElement.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/information/OfflineAllowedElement.java @@ -1,24 +1,24 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.information; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public @simpl_tag("offline-allowed") class OfflineAllowedElement extends ElementState -{ - - /** - * - */ - public OfflineAllowedElement() - { - super(); - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.information; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public @simpl_tag("offline-allowed") class OfflineAllowedElement extends ElementState +{ + + /** + * + */ + public OfflineAllowedElement() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/information/RelatedContentElement.java b/simplCore/src/ecologylab/serialization/library/jnlp/information/RelatedContentElement.java index ae6dd416..b1d71f78 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/information/RelatedContentElement.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/information/RelatedContentElement.java @@ -1,41 +1,41 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.information; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * related-content element: The optional related-content element describes an additional piece of related content, such - * as a readme file, help pages, or links to registration pages, as a hint to a JNLP Client. The application is asking - * that this content be included in its desktop integration. The related-content element has a mandatory href and title - * attribute. It can contain any of the following two sub-elements: - * - * description element: A short description of the related content. icon element: The icon can be used by the JNLP - * Client to identify the related content to the user. - * - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class RelatedContentElement extends ElementState -{ - @simpl_scalar private String href; - - @simpl_scalar private String title; - - @simpl_composite private Description description; - - @simpl_composite private Icon icon; - - /** - * - */ - public RelatedContentElement() - { - // TODO Auto-generated constructor stub - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.information; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * related-content element: The optional related-content element describes an additional piece of related content, such + * as a readme file, help pages, or links to registration pages, as a hint to a JNLP Client. The application is asking + * that this content be included in its desktop integration. The related-content element has a mandatory href and title + * attribute. It can contain any of the following two sub-elements: + * + * description element: A short description of the related content. icon element: The icon can be used by the JNLP + * Client to identify the related content to the user. + * + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class RelatedContentElement extends ElementState +{ + @simpl_scalar private String href; + + @simpl_scalar private String title; + + @simpl_composite private Description description; + + @simpl_composite private Icon icon; + + /** + * + */ + public RelatedContentElement() + { + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/information/ShortcutElement.java b/simplCore/src/ecologylab/serialization/library/jnlp/information/ShortcutElement.java index 9217d374..b3b6f36d 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/information/ShortcutElement.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/information/ShortcutElement.java @@ -1,33 +1,33 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.information; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * shortcut element: The optional shortcut element can be used to indicate an application's preferences for desktop - * integration. The shortcut element and it's sub-elements provide hints that the JNLP Client may or may not use. The - * shortcut element can contain the optional online attribute, and the two optional sub-elements, desktop and menu. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class ShortcutElement extends ElementState -{ - @simpl_scalar private boolean online; - - @simpl_composite private ElementState desktop; - - @simpl_composite private MenuElement menu; - - /** - * - */ - public ShortcutElement() - { - super(); - } -} +/** + * + */ +package ecologylab.serialization.library.jnlp.information; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * shortcut element: The optional shortcut element can be used to indicate an application's preferences for desktop + * integration. The shortcut element and it's sub-elements provide hints that the JNLP Client may or may not use. The + * shortcut element can contain the optional online attribute, and the two optional sub-elements, desktop and menu. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class ShortcutElement extends ElementState +{ + @simpl_scalar private boolean online; + + @simpl_composite private ElementState desktop; + + @simpl_composite private MenuElement menu; + + /** + * + */ + public ShortcutElement() + { + super(); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/package.html b/simplCore/src/ecologylab/serialization/library/jnlp/package.html index 5bc833e0..3ce29aa7 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/package.html +++ b/simplCore/src/ecologylab/serialization/library/jnlp/package.html @@ -1,5 +1,5 @@ - -{@link ecologylab.xml.ElementState ElementState} - subclasses that enable translation of XML entities from the -Java Network Launch Protocol namespace. - + +{@link ecologylab.xml.ElementState ElementState} + subclasses that enable translation of XML entities from the +Java Network Launch Protocol namespace. + diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/resource/HrefBasedResource.java b/simplCore/src/ecologylab/serialization/library/jnlp/resource/HrefBasedResource.java index 9fb976d2..5550a01c 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/resource/HrefBasedResource.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/resource/HrefBasedResource.java @@ -1,24 +1,24 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.resource; - -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class HrefBasedResource extends ResourceElement -{ - @simpl_scalar private String href; - - /** - * - */ - public HrefBasedResource() - { - super(); - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.resource; + +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class HrefBasedResource extends ResourceElement +{ + @simpl_scalar private String href; + + /** + * + */ + public HrefBasedResource() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/resource/J2se.java b/simplCore/src/ecologylab/serialization/library/jnlp/resource/J2se.java index 7a2ac744..3ee86f38 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/resource/J2se.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/resource/J2se.java @@ -1,81 +1,81 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.resource; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * The j2se element specifies what Java 2 SE Runtime Environment (JRE) versions an application is supported on, as well - * as standard parameters to the Java Virtual Machine. If several JREs are specified, this indicates a prioritized list - * of the supported JREs, with the most preferred version first. For example: - * - * - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public @simpl_inherit @simpl_tag("j2se") class J2se extends HrefBasedResource -{ - /** - * The version attribute refers, by default, to a platform version (specification version) of the Java 2 platform. - * Currently defined platform versions are 1.2, 1.3, 1.4 and 1.5. (A platform version will not normally contain a - * micro version number; e.g., 1.4.2.) - * - * Exact product versions (implementation versions) may also be specified. by including the href attribute. For - * example, 1.3.1_07, 1.4.2, or 1.5.0-beta2 by Sun Microsystems, Inc. For example, - * - * - * - * If a platform version is specified (i.e., no href attribute is provided), Java Web Start will not consider an - * installed non-FCS (i.e., milestone) JRE as a match. E.g., a request of the form - * - * - * - * would not consider an installed 1.4.1-ea or 1.4.2-beta JRE as a match for the request. Starting with 1.3.0, a JRE - * from Sun Microsystems, Inc., is by convention a non-FCS (milestone) JRE if there is a dash (-) in the version - * string. - */ - @simpl_scalar private String version; - - /** - * The java-vm-args attribute of the j2se element specifies a preferred set of virtual machine arguments to use when - * launching java. - * - * - * - * The following java-vm-args are supported by this version: - * - * -client -server -verbose -showversion -esa -enablesystemassertions -dsa -disablesystemassertions -Xmixed -Xint - * -Xnoclassgc -Xincgc -Xbatch -Xprof -Xdebug -Xrs -XX:+ForceTimeHighResolution -XX:-ForceTimeHighResolution - * - * Plus any argument starting with one of the following: - * - * -ea: -enableassertions: -da: -disableassertions: -verbose: -Xms -Xmx -Xss -XX:NewRatio -XX:NewSize -XX:MaxNewSize - * -XX:PermSize -XX:MaxPermSize -XX:MaxHeapFreeRatio -XX:MinHeapFreeRatio -XX:UseSerialGC -XX:ThreadStackSize - * -XX:MaxInlineSize -XX:ReservedCodeCacheSize - * - * - */ - @simpl_scalar @simpl_tag("java-vm-args") private String javaVmArgs; - - @simpl_scalar @simpl_tag("initial-heap-size") private String initialHeapSize; - - @simpl_scalar @simpl_tag("max-heap-size") private String maxHeapSize; - - /** - * - */ - public J2se() - { - super(); - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.resource; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * The j2se element specifies what Java 2 SE Runtime Environment (JRE) versions an application is supported on, as well + * as standard parameters to the Java Virtual Machine. If several JREs are specified, this indicates a prioritized list + * of the supported JREs, with the most preferred version first. For example: + * + * + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public @simpl_inherit @simpl_tag("j2se") class J2se extends HrefBasedResource +{ + /** + * The version attribute refers, by default, to a platform version (specification version) of the Java 2 platform. + * Currently defined platform versions are 1.2, 1.3, 1.4 and 1.5. (A platform version will not normally contain a + * micro version number; e.g., 1.4.2.) + * + * Exact product versions (implementation versions) may also be specified. by including the href attribute. For + * example, 1.3.1_07, 1.4.2, or 1.5.0-beta2 by Sun Microsystems, Inc. For example, + * + * + * + * If a platform version is specified (i.e., no href attribute is provided), Java Web Start will not consider an + * installed non-FCS (i.e., milestone) JRE as a match. E.g., a request of the form + * + * + * + * would not consider an installed 1.4.1-ea or 1.4.2-beta JRE as a match for the request. Starting with 1.3.0, a JRE + * from Sun Microsystems, Inc., is by convention a non-FCS (milestone) JRE if there is a dash (-) in the version + * string. + */ + @simpl_scalar private String version; + + /** + * The java-vm-args attribute of the j2se element specifies a preferred set of virtual machine arguments to use when + * launching java. + * + * + * + * The following java-vm-args are supported by this version: + * + * -client -server -verbose -showversion -esa -enablesystemassertions -dsa -disablesystemassertions -Xmixed -Xint + * -Xnoclassgc -Xincgc -Xbatch -Xprof -Xdebug -Xrs -XX:+ForceTimeHighResolution -XX:-ForceTimeHighResolution + * + * Plus any argument starting with one of the following: + * + * -ea: -enableassertions: -da: -disableassertions: -verbose: -Xms -Xmx -Xss -XX:NewRatio -XX:NewSize -XX:MaxNewSize + * -XX:PermSize -XX:MaxPermSize -XX:MaxHeapFreeRatio -XX:MinHeapFreeRatio -XX:UseSerialGC -XX:ThreadStackSize + * -XX:MaxInlineSize -XX:ReservedCodeCacheSize + * + * + */ + @simpl_scalar @simpl_tag("java-vm-args") private String javaVmArgs; + + @simpl_scalar @simpl_tag("initial-heap-size") private String initialHeapSize; + + @simpl_scalar @simpl_tag("max-heap-size") private String maxHeapSize; + + /** + * + */ + public J2se() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/resource/Jar.java b/simplCore/src/ecologylab/serialization/library/jnlp/resource/Jar.java index c03bad5c..03324aeb 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/resource/Jar.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/resource/Jar.java @@ -1,37 +1,37 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.resource; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * A jar element specifies a JAR file that is part of the application's classpath. For example: - * - * - * - * The jar file will be loaded into the JVM using a ClassLoader object. The jar file will typically contain Java classes - * that contain the code for the particular application, but can also contain other resources, such as icons and - * configuration files, that are available through the getResource mechanism. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public @simpl_inherit class Jar extends HrefBasedResource -{ - /** - * The download attribute is used to control whether a resource is downloaded eagerly or lazily. For example: - * - * - */ - @simpl_scalar protected String download; - - /** - * - */ - public Jar() - { - super(); - } -} +/** + * + */ +package ecologylab.serialization.library.jnlp.resource; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * A jar element specifies a JAR file that is part of the application's classpath. For example: + * + * + * + * The jar file will be loaded into the JVM using a ClassLoader object. The jar file will typically contain Java classes + * that contain the code for the particular application, but can also contain other resources, such as icons and + * configuration files, that are available through the getResource mechanism. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public @simpl_inherit class Jar extends HrefBasedResource +{ + /** + * The download attribute is used to control whether a resource is downloaded eagerly or lazily. For example: + * + * + */ + @simpl_scalar protected String download; + + /** + * + */ + public Jar() + { + super(); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/resource/Nativelib.java b/simplCore/src/ecologylab/serialization/library/jnlp/resource/Nativelib.java index 07f63adf..de9b7214 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/resource/Nativelib.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/resource/Nativelib.java @@ -1,42 +1,42 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.resource; - -import ecologylab.serialization.annotations.simpl_inherit; - -/** - * A nativelib element specifies a JAR file that contains native libraries. For example: - * - * - * - * The JNLP client must ensure that each file entry in the root directory of the JAR file (i.e., /) can be loaded into - * the running process using the System.loadLibrary method. Each entry must contain a platform-dependent shared library - * with the correct naming convention, e.g., *.dll on Windows or lib*.so on Solaris/Linux. The application is - * responsible for doing the actual call to System.loadLibrary. - * - * Native libraries would typically be included in a resources element that is geared toward a particular operating - * system and architecture. For example: - * - * - * - * By default, jar and nativelib resources will be downloaded eagerly, i.e., they are downloaded and available locally - * to the JVM running the application before the application is launched. The jar and nativelib elements also allow a - * resource to be specified as lazy. This means the resource does not have to be downloaded onto the client system - * before the application is launched. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public @simpl_inherit class Nativelib extends Jar -{ - - /** - * - */ - public Nativelib() - { - super(); - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.resource; + +import ecologylab.serialization.annotations.simpl_inherit; + +/** + * A nativelib element specifies a JAR file that contains native libraries. For example: + * + * + * + * The JNLP client must ensure that each file entry in the root directory of the JAR file (i.e., /) can be loaded into + * the running process using the System.loadLibrary method. Each entry must contain a platform-dependent shared library + * with the correct naming convention, e.g., *.dll on Windows or lib*.so on Solaris/Linux. The application is + * responsible for doing the actual call to System.loadLibrary. + * + * Native libraries would typically be included in a resources element that is geared toward a particular operating + * system and architecture. For example: + * + * + * + * By default, jar and nativelib resources will be downloaded eagerly, i.e., they are downloaded and available locally + * to the JVM running the application before the application is launched. The jar and nativelib elements also allow a + * resource to be specified as lazy. This means the resource does not have to be downloaded onto the client system + * before the application is launched. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public @simpl_inherit class Nativelib extends Jar +{ + + /** + * + */ + public Nativelib() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/resource/Property.java b/simplCore/src/ecologylab/serialization/library/jnlp/resource/Property.java index bc25ac07..323e2f90 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/resource/Property.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/resource/Property.java @@ -1,42 +1,42 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.resource; - -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * The property element defines a system property that will be available through the System.getProperty and - * System.setProperties methods. It has two required attributes: name and value. For example: - * - * - * - * Properties set in the jnlp file will normally be set by Java Web Start after the VM is started but before the - * application is invoked. Some properties are considered "secure" properties and can be passed as -Dkey=value arguments - * on the java invocation command line. - * - * The following properties are considered "secure" and will be passed to the VM in this way: - * - * sun.java2d.noddraw javaws.cfg.jauthenticator swing.useSystemFontSettings swing.metalTheme http.agent http.keepAlive - * - * For an untrusted application, system properties set in the JNLP file will only be set by Java Web Start if they are - * considered secure, or if the property name begins with "jnlp." or "javaws.". - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class Property extends ResourceElement -{ - @simpl_scalar private String name; - - @simpl_scalar private String value; - - /** - * - */ - public Property() - { - // TODO Auto-generated constructor stub - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.resource; + +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * The property element defines a system property that will be available through the System.getProperty and + * System.setProperties methods. It has two required attributes: name and value. For example: + * + * + * + * Properties set in the jnlp file will normally be set by Java Web Start after the VM is started but before the + * application is invoked. Some properties are considered "secure" properties and can be passed as -Dkey=value arguments + * on the java invocation command line. + * + * The following properties are considered "secure" and will be passed to the VM in this way: + * + * sun.java2d.noddraw javaws.cfg.jauthenticator swing.useSystemFontSettings swing.metalTheme http.agent http.keepAlive + * + * For an untrusted application, system properties set in the JNLP file will only be set by Java Web Start if they are + * considered secure, or if the property name begins with "jnlp." or "javaws.". + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class Property extends ResourceElement +{ + @simpl_scalar private String name; + + @simpl_scalar private String value; + + /** + * + */ + public Property() + { + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/resource/ResourceElement.java b/simplCore/src/ecologylab/serialization/library/jnlp/resource/ResourceElement.java index d240b77f..7199efad 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/resource/ResourceElement.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/resource/ResourceElement.java @@ -1,22 +1,22 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.resource; - -import ecologylab.serialization.ElementState; - -/** - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class ResourceElement extends ElementState -{ - /** - * - */ - public ResourceElement() - { - // TODO Auto-generated constructor stub - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.resource; + +import ecologylab.serialization.ElementState; + +/** + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class ResourceElement extends ElementState +{ + /** + * + */ + public ResourceElement() + { + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/jnlp/resource/ResourceElementArray.java b/simplCore/src/ecologylab/serialization/library/jnlp/resource/ResourceElementArray.java index fe16a94d..a31e8707 100644 --- a/simplCore/src/ecologylab/serialization/library/jnlp/resource/ResourceElementArray.java +++ b/simplCore/src/ecologylab/serialization/library/jnlp/resource/ResourceElementArray.java @@ -1,48 +1,48 @@ -/** - * - */ -package ecologylab.serialization.library.jnlp.resource; - -import java.util.ArrayList; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_classes; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * The resources element is used to specify all the resources, such as Java class files, native - * libraries, and system properties, that are part of the application. A resource definition can be - * restricted to a specific operating system, architecture, or locale using the os, arch, and locale - * attributes. - * - * @author Zachary O. Toups (zach@ecologylab.net) - * - */ -public class ResourceElementArray extends ElementState -{ - @simpl_scalar - private String os; - - @simpl_scalar - private String arch; - - @simpl_scalar - private String locale; - - @simpl_collection - @simpl_nowrap - @simpl_classes( - { ResourceElement.class, HrefBasedResource.class, J2se.class, Jar.class }) - ArrayList resourceElements; - - /** - * - */ - public ResourceElementArray() - { - super(); - } - -} +/** + * + */ +package ecologylab.serialization.library.jnlp.resource; + +import java.util.ArrayList; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_classes; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * The resources element is used to specify all the resources, such as Java class files, native + * libraries, and system properties, that are part of the application. A resource definition can be + * restricted to a specific operating system, architecture, or locale using the os, arch, and locale + * attributes. + * + * @author Zachary O. Toups (zach@ecologylab.net) + * + */ +public class ResourceElementArray extends ElementState +{ + @simpl_scalar + private String os; + + @simpl_scalar + private String arch; + + @simpl_scalar + private String locale; + + @simpl_collection + @simpl_nowrap + @simpl_classes( + { ResourceElement.class, HrefBasedResource.class, J2se.class, Jar.class }) + ArrayList resourceElements; + + /** + * + */ + public ResourceElementArray() + { + super(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/media/Content.java b/simplCore/src/ecologylab/serialization/library/media/Content.java index 43b63d09..b7cbb84a 100644 --- a/simplCore/src/ecologylab/serialization/library/media/Content.java +++ b/simplCore/src/ecologylab/serialization/library/media/Content.java @@ -1,211 +1,211 @@ -package ecologylab.serialization.library.media; - -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Primary element of the media XML name space. As in - * - * @author andruid - */ -public class Content extends ElementState -{ - @simpl_scalar ParsedURL url; - @simpl_scalar String type; - @simpl_scalar int width; - @simpl_scalar int height; - - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; - @simpl_composite Description description; - @simpl_scalar String keywords; - @simpl_composite Thumbnail thumbnail; - - // there can be 0 or more elements of tag "category" - // we will add these to a collection automatically by overriding setField(Field, String) - //TODO confirm if this is correct. - @simpl_collection ArrayList categoryStrings; - - @simpl_composite Credit credit; - - //public String text -- actually there can be many of these - //public String restriction; // a leaf node - // - - - public Content() - { - super(); - } - - /** - * Lazy evaluation avoids unnecessary allocations. - * - * Note: a different accessor is needed for external calls -- - * one that won't allocate on demand. - * - * @return Returns the categoryStrings. - */ - protected ArrayList evalCategoryStrings() - { - ArrayList result = categoryStrings; - if (categoryStrings == null) - { - result = new ArrayList(5); - categoryStrings = result; - } - return result; - } - - /** - * @return Returns the credit. - */ - public Credit getCredit() - { - return credit; - } - - /** - * @param credit The credit to set. - */ - public void setCredit(Credit credit) - { - this.credit = credit; - } - - /** - * @return Returns the description. - */ - public Description getDescription() - { - return description; - } - - /** - * @param description The description to set. - */ - public void setDescription(Description description) - { - this.description = description; - } - - /** - * @return Returns the height. - */ - public int getHeight() - { - return height; - } - - /** - * @param height The height to set. - */ - public void setHeight(int height) - { - this.height = height; - } - - /** - * @return Returns the keywords. - */ - public String getKeywords() - { - return keywords; - } - - /** - * @param keywords The keywords to set. - */ - public void setKeywords(String keywords) - { - this.keywords = keywords; - } - - /** - * @return Returns the thumbnail. - */ - public Thumbnail getThumbnail() - { - return thumbnail; - } - - /** - * @param thumbnail The thumbnail to set. - */ - public void setThumbnail(Thumbnail thumbnail) - { - this.thumbnail = thumbnail; - } - - /** - * @return Returns the title. - */ - public String getTitle() - { - return title; - } - - /** - * @param title The title to set. - */ - public void setTitle(String title) - { - this.title = title; - } - - /** - * @return Returns the type. - */ - public String getType() - { - return type; - } - - /** - * @param type The type to set. - */ - public void setType(String type) - { - this.type = type; - } - - /** - * @return Returns the url. - */ - public ParsedURL getUrl() - { - return url; - } - - /** - * @param url The url to set. - */ - public void setUrl(ParsedURL url) - { - this.url = url; - } - - /** - * @return Returns the width. - */ - public int getWidth() - { - return width; - } - - /** - * @param width The width to set. - */ - public void setWidth(int width) - { - this.width = width; - } - - -} +package ecologylab.serialization.library.media; + +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Primary element of the media XML name space. As in + * + * @author andruid + */ +public class Content extends ElementState +{ + @simpl_scalar ParsedURL url; + @simpl_scalar String type; + @simpl_scalar int width; + @simpl_scalar int height; + + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; + @simpl_composite Description description; + @simpl_scalar String keywords; + @simpl_composite Thumbnail thumbnail; + + // there can be 0 or more elements of tag "category" + // we will add these to a collection automatically by overriding setField(Field, String) + //TODO confirm if this is correct. + @simpl_collection ArrayList categoryStrings; + + @simpl_composite Credit credit; + + //public String text -- actually there can be many of these + //public String restriction; // a leaf node + // + + + public Content() + { + super(); + } + + /** + * Lazy evaluation avoids unnecessary allocations. + * + * Note: a different accessor is needed for external calls -- + * one that won't allocate on demand. + * + * @return Returns the categoryStrings. + */ + protected ArrayList evalCategoryStrings() + { + ArrayList result = categoryStrings; + if (categoryStrings == null) + { + result = new ArrayList(5); + categoryStrings = result; + } + return result; + } + + /** + * @return Returns the credit. + */ + public Credit getCredit() + { + return credit; + } + + /** + * @param credit The credit to set. + */ + public void setCredit(Credit credit) + { + this.credit = credit; + } + + /** + * @return Returns the description. + */ + public Description getDescription() + { + return description; + } + + /** + * @param description The description to set. + */ + public void setDescription(Description description) + { + this.description = description; + } + + /** + * @return Returns the height. + */ + public int getHeight() + { + return height; + } + + /** + * @param height The height to set. + */ + public void setHeight(int height) + { + this.height = height; + } + + /** + * @return Returns the keywords. + */ + public String getKeywords() + { + return keywords; + } + + /** + * @param keywords The keywords to set. + */ + public void setKeywords(String keywords) + { + this.keywords = keywords; + } + + /** + * @return Returns the thumbnail. + */ + public Thumbnail getThumbnail() + { + return thumbnail; + } + + /** + * @param thumbnail The thumbnail to set. + */ + public void setThumbnail(Thumbnail thumbnail) + { + this.thumbnail = thumbnail; + } + + /** + * @return Returns the title. + */ + public String getTitle() + { + return title; + } + + /** + * @param title The title to set. + */ + public void setTitle(String title) + { + this.title = title; + } + + /** + * @return Returns the type. + */ + public String getType() + { + return type; + } + + /** + * @param type The type to set. + */ + public void setType(String type) + { + this.type = type; + } + + /** + * @return Returns the url. + */ + public ParsedURL getUrl() + { + return url; + } + + /** + * @param url The url to set. + */ + public void setUrl(ParsedURL url) + { + this.url = url; + } + + /** + * @return Returns the width. + */ + public int getWidth() + { + return width; + } + + /** + * @param width The width to set. + */ + public void setWidth(int width) + { + this.width = width; + } + + +} diff --git a/simplCore/src/ecologylab/serialization/library/media/Credit.java b/simplCore/src/ecologylab/serialization/library/media/Credit.java index fe74625b..0ab17792 100644 --- a/simplCore/src/ecologylab/serialization/library/media/Credit.java +++ b/simplCore/src/ecologylab/serialization/library/media/Credit.java @@ -1,31 +1,31 @@ -package ecologylab.serialization.library.media; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Leaf node with attributes (so not declared as such). - * The actual value is a Text node. - * - * @author andruid - */ -public class Credit extends ElementState -{ - @simpl_scalar String role; - - /** - * @return Returns the role. - */ - protected String getRole() - { - return role; - } - - /** - * @param role The role to set. - */ - protected void setRole(String role) - { - this.role = role; - } -} +package ecologylab.serialization.library.media; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Leaf node with attributes (so not declared as such). + * The actual value is a Text node. + * + * @author andruid + */ +public class Credit extends ElementState +{ + @simpl_scalar String role; + + /** + * @return Returns the role. + */ + protected String getRole() + { + return role; + } + + /** + * @param role The role to set. + */ + protected void setRole(String role) + { + this.role = role; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/media/Description.java b/simplCore/src/ecologylab/serialization/library/media/Description.java index 31f819ab..981de799 100644 --- a/simplCore/src/ecologylab/serialization/library/media/Description.java +++ b/simplCore/src/ecologylab/serialization/library/media/Description.java @@ -1,37 +1,37 @@ -package ecologylab.serialization.library.media; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Media leaf node, but not marked up as such cause it has its own attribute. - * - * @author andruid - */ -public class Description extends ElementState -{ -/** - * Can be plain or html. Plain is the default. - */ - @simpl_scalar String type; - - /** - * @return Returns the type. - */ - protected String getType() - { - return type; - } - - /** - * @param type The type to set. - */ - protected void setType(String type) - { - this.type = type; - } - - /** - * A text node will be here with the actual description. - */ -} +package ecologylab.serialization.library.media; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Media leaf node, but not marked up as such cause it has its own attribute. + * + * @author andruid + */ +public class Description extends ElementState +{ +/** + * Can be plain or html. Plain is the default. + */ + @simpl_scalar String type; + + /** + * @return Returns the type. + */ + protected String getType() + { + return type; + } + + /** + * @param type The type to set. + */ + protected void setType(String type) + { + this.type = type; + } + + /** + * A text node will be here with the actual description. + */ +} diff --git a/simplCore/src/ecologylab/serialization/library/media/Group.java b/simplCore/src/ecologylab/serialization/library/media/Group.java index de94b46f..defd4443 100644 --- a/simplCore/src/ecologylab/serialization/library/media/Group.java +++ b/simplCore/src/ecologylab/serialization/library/media/Group.java @@ -1,33 +1,33 @@ -/** - * - */ -package ecologylab.serialization.library.media; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_composite; - -/** - * Yahoo Media XML Namespace Group element. - * Found in abcnews. - * - * @author andruid - */ -public class Group extends ElementState -{ - @simpl_composite Thumbnail thumbnail; - - /** - * Lookup a NestedNameSpace element child of this, in case there is one, - * declared as xmlns:media. - * Yahoo Media metadata declarations. - * - * @return Returns the Media nested namespace element, or null.. - */ - public Media lookupMedia() - { - return null; - //return (Media) lookupNestedNameSpace("media"); - } - - -} +/** + * + */ +package ecologylab.serialization.library.media; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_composite; + +/** + * Yahoo Media XML Namespace Group element. + * Found in abcnews. + * + * @author andruid + */ +public class Group extends ElementState +{ + @simpl_composite Thumbnail thumbnail; + + /** + * Lookup a NestedNameSpace element child of this, in case there is one, + * declared as xmlns:media. + * Yahoo Media metadata declarations. + * + * @return Returns the Media nested namespace element, or null.. + */ + public Media lookupMedia() + { + return null; + //return (Media) lookupNestedNameSpace("media"); + } + + +} diff --git a/simplCore/src/ecologylab/serialization/library/media/Media.java b/simplCore/src/ecologylab/serialization/library/media/Media.java index 7e819ecb..b5f75fb9 100644 --- a/simplCore/src/ecologylab/serialization/library/media/Media.java +++ b/simplCore/src/ecologylab/serialization/library/media/Media.java @@ -1,180 +1,180 @@ -package ecologylab.serialization.library.media; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Root class for inserting elements from the Yahoo Media XML Namespace. - * - * See http://search.yahoo.com/mrss - * - * @author andruid - */ -public class Media extends ElementState -{ - /** - * A single Content element in the Yahoo schema. - *

- * An alternative would be to implement this as an ArrayListState, and be able - * to aggregate a set of these. We can do this when there is a need, with an example. - */ - @simpl_composite Content content; - - @simpl_composite Credit credit; - - @simpl_composite Thumbnail thumbnail; - - @simpl_composite Group group; - - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; - - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String category; - - //FIXME -- need to implement @simpl_scalar @simpl_hints(Hint.XML_TEXT) directive to parse this properly. - // not a leaf! may have type attribute. - // it would also be very nice if the parser knew to warn about and then - // throw away attributes found inside elements declared as leaf. - -// @simpl_scalar @simpl_hints(Hint.XML_LEAF) String text; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String rating; - /** - * @return Returns the category. - */ - public String getCategory() - { - return category; - } - /** - * @param category The category to set. - */ - public void setCategory(String category) - { - this.category = category; - } - /** - * @return Returns the content. - */ - public Content getContent() - { - return content; - } - /** - * @param content The content to set. - */ - public void setContent(Content content) - { - this.content = content; - } - /** - * @return Returns the rating. - */ - public String getRating() - { - return rating; - } - /** - * @param rating The rating to set. - */ - public void setRating(String rating) - { - this.rating = rating; - } - /** - * @return Returns the text. - */ - - public String getTitle() { - return title; - } - public void setTitle(String title) { - this.title = title; - } - public String getDescription() { - return description; - } - public void setDescription(String description) { - this.description = description; - } - /** - * @return Returns the credit. - */ - public Credit getCredit() - { - return credit; - } - /** - * @param credit The credit to set. - */ - public void setCredit(Credit credit) - { - this.credit = credit; - } - - private static final String TRANSLATION_SPACE_NAME = "yahoo_media"; - - public static final Class TRANSLATIONS[] = - { - Media.class, - Thumbnail.class, - Content.class, - Description.class, - Credit.class, - - }; - - /** - * TranslationSpace for Yahoo Media. - * - * @return - */ - public static final SimplTypesScope getTranslations() - { - return SimplTypesScope.get(TRANSLATION_SPACE_NAME, TRANSLATIONS); - } - /** - * @return the thumbnail - */ - public Thumbnail getThumbnail() - { - Thumbnail result = thumbnail; - - if (result == null) - { - Group group = this.group; - if (group != null) - { - Media nestedMedia = group.lookupMedia(); - if (nestedMedia != null) - result = nestedMedia.getThumbnail(); - } - } - - return result; - } - /** - * @param thumbnail the thumbnail to set - */ - public void setThumbnail(Thumbnail thumbnail) - { - this.thumbnail = thumbnail; - } - /** - * @return the group - */ - public Group getGroup() - { - return group; - } - /** - * @param group the group to set - */ - public void setGroup(Group group) - { - this.group = group; - } -} +package ecologylab.serialization.library.media; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Root class for inserting elements from the Yahoo Media XML Namespace. + * + * See http://search.yahoo.com/mrss + * + * @author andruid + */ +public class Media extends ElementState +{ + /** + * A single Content element in the Yahoo schema. + *

+ * An alternative would be to implement this as an ArrayListState, and be able + * to aggregate a set of these. We can do this when there is a need, with an example. + */ + @simpl_composite Content content; + + @simpl_composite Credit credit; + + @simpl_composite Thumbnail thumbnail; + + @simpl_composite Group group; + + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; + + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String category; + + //FIXME -- need to implement @simpl_scalar @simpl_hints(Hint.XML_TEXT) directive to parse this properly. + // not a leaf! may have type attribute. + // it would also be very nice if the parser knew to warn about and then + // throw away attributes found inside elements declared as leaf. + +// @simpl_scalar @simpl_hints(Hint.XML_LEAF) String text; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String rating; + /** + * @return Returns the category. + */ + public String getCategory() + { + return category; + } + /** + * @param category The category to set. + */ + public void setCategory(String category) + { + this.category = category; + } + /** + * @return Returns the content. + */ + public Content getContent() + { + return content; + } + /** + * @param content The content to set. + */ + public void setContent(Content content) + { + this.content = content; + } + /** + * @return Returns the rating. + */ + public String getRating() + { + return rating; + } + /** + * @param rating The rating to set. + */ + public void setRating(String rating) + { + this.rating = rating; + } + /** + * @return Returns the text. + */ + + public String getTitle() { + return title; + } + public void setTitle(String title) { + this.title = title; + } + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + /** + * @return Returns the credit. + */ + public Credit getCredit() + { + return credit; + } + /** + * @param credit The credit to set. + */ + public void setCredit(Credit credit) + { + this.credit = credit; + } + + private static final String TRANSLATION_SPACE_NAME = "yahoo_media"; + + public static final Class TRANSLATIONS[] = + { + Media.class, + Thumbnail.class, + Content.class, + Description.class, + Credit.class, + + }; + + /** + * TranslationSpace for Yahoo Media. + * + * @return + */ + public static final SimplTypesScope getTranslations() + { + return SimplTypesScope.get(TRANSLATION_SPACE_NAME, TRANSLATIONS); + } + /** + * @return the thumbnail + */ + public Thumbnail getThumbnail() + { + Thumbnail result = thumbnail; + + if (result == null) + { + Group group = this.group; + if (group != null) + { + Media nestedMedia = group.lookupMedia(); + if (nestedMedia != null) + result = nestedMedia.getThumbnail(); + } + } + + return result; + } + /** + * @param thumbnail the thumbnail to set + */ + public void setThumbnail(Thumbnail thumbnail) + { + this.thumbnail = thumbnail; + } + /** + * @return the group + */ + public Group getGroup() + { + return group; + } + /** + * @param group the group to set + */ + public void setGroup(Group group) + { + this.group = group; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/media/Thumbnail.java b/simplCore/src/ecologylab/serialization/library/media/Thumbnail.java index 1604020c..6af86071 100644 --- a/simplCore/src/ecologylab/serialization/library/media/Thumbnail.java +++ b/simplCore/src/ecologylab/serialization/library/media/Thumbnail.java @@ -1,65 +1,65 @@ -package ecologylab.serialization.library.media; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Thumbnail element. Optionally used to provide representative images - * for a rich media object. - * - * @author andruid - */ -public class Thumbnail extends ElementState -{ - @simpl_scalar ParsedURL url; - @simpl_scalar int width; - @simpl_scalar int height; - - - /** - * @return the url - */ - public ParsedURL getUrl() - { - return url; - } - /** - * @param url the url to set - */ - public void setUrl(ParsedURL url) - { - this.url = url; - } - /** - * @return the width - */ - public int getWidth() - { - return width; - } - /** - * @param width the width to set - */ - public void setWidth(int width) - { - this.width = width; - } - /** - * @return the height - */ - public int getHeight() - { - return height; - } - /** - * @param height the height to set - */ - public void setHeight(int height) - { - this.height = height; - } - - //time -- represents offset into time-based media object. for key frames. - //http://www.ietf.org/rfc/rfc2326.txt -} +package ecologylab.serialization.library.media; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Thumbnail element. Optionally used to provide representative images + * for a rich media object. + * + * @author andruid + */ +public class Thumbnail extends ElementState +{ + @simpl_scalar ParsedURL url; + @simpl_scalar int width; + @simpl_scalar int height; + + + /** + * @return the url + */ + public ParsedURL getUrl() + { + return url; + } + /** + * @param url the url to set + */ + public void setUrl(ParsedURL url) + { + this.url = url; + } + /** + * @return the width + */ + public int getWidth() + { + return width; + } + /** + * @param width the width to set + */ + public void setWidth(int width) + { + this.width = width; + } + /** + * @return the height + */ + public int getHeight() + { + return height; + } + /** + * @param height the height to set + */ + public void setHeight(int height) + { + this.height = height; + } + + //time -- represents offset into time-based media object. for key frames. + //http://www.ietf.org/rfc/rfc2326.txt +} diff --git a/simplCore/src/ecologylab/serialization/library/media/package.html b/simplCore/src/ecologylab/serialization/library/media/package.html index 1d495c82..a7af61f5 100644 --- a/simplCore/src/ecologylab/serialization/library/media/package.html +++ b/simplCore/src/ecologylab/serialization/library/media/package.html @@ -1,5 +1,5 @@ - -{@link ecologylab.xml.ElementState ElementState} - subclasses that enable translation of XML entities from the -Yahoo media specification. - + +{@link ecologylab.xml.ElementState ElementState} + subclasses that enable translation of XML entities from the +Yahoo media specification. + diff --git a/simplCore/src/ecologylab/serialization/library/opml/Body.java b/simplCore/src/ecologylab/serialization/library/opml/Body.java index e53acff6..a6f75c7d 100644 --- a/simplCore/src/ecologylab/serialization/library/opml/Body.java +++ b/simplCore/src/ecologylab/serialization/library/opml/Body.java @@ -1,43 +1,43 @@ -/** - * - */ -package ecologylab.serialization.library.opml; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_composite; - -/** - * OPML element - * - * @author andruid - */ -public class Body extends ElementState -{ - @simpl_composite Outline outline; - - /** - * - */ - public Body() - { - super(); - - } - - /** - * @return Returns the outline. - */ - public Outline getOutline() - { - return outline; - } - - /** - * @param outline The outline to set. - */ - public void setOutline(Outline outline) - { - this.outline = outline; - } - -} +/** + * + */ +package ecologylab.serialization.library.opml; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_composite; + +/** + * OPML element + * + * @author andruid + */ +public class Body extends ElementState +{ + @simpl_composite Outline outline; + + /** + * + */ + public Body() + { + super(); + + } + + /** + * @return Returns the outline. + */ + public Outline getOutline() + { + return outline; + } + + /** + * @param outline The outline to set. + */ + public void setOutline(Outline outline) + { + this.outline = outline; + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/opml/Opml.java b/simplCore/src/ecologylab/serialization/library/opml/Opml.java index a59d0f24..090851e7 100644 --- a/simplCore/src/ecologylab/serialization/library/opml/Opml.java +++ b/simplCore/src/ecologylab/serialization/library/opml/Opml.java @@ -1,58 +1,58 @@ -/** - * - */ -package ecologylab.serialization.library.opml; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_composite; - -/** - * Outline Processor Markup Language root element. - * - * @author andruid - */ -public class Opml extends ElementState -{ - @simpl_composite Body body; - - /** - * - */ - public Opml() - { - super(); - } - - public static final String PACKAGE_NAME = "ecologylab.serialization.library.opml"; - - public static final Class TRANSLATIONS[] = - { - Opml.class, - Body.class, - Outline.class, - }; - /** - * Get an appropriate TranslationSpace for OPML. - * - * @return - */ - public static SimplTypesScope getTranslationScope() - { - return SimplTypesScope.get(PACKAGE_NAME, TRANSLATIONS); - } - /** - * @return Returns the body. - */ - public Body getBody() - { - return body; - } - /** - * @param body The body to set. - */ - public void setBody(Body body) - { - this.body = body; - } -} +/** + * + */ +package ecologylab.serialization.library.opml; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_composite; + +/** + * Outline Processor Markup Language root element. + * + * @author andruid + */ +public class Opml extends ElementState +{ + @simpl_composite Body body; + + /** + * + */ + public Opml() + { + super(); + } + + public static final String PACKAGE_NAME = "ecologylab.serialization.library.opml"; + + public static final Class TRANSLATIONS[] = + { + Opml.class, + Body.class, + Outline.class, + }; + /** + * Get an appropriate TranslationSpace for OPML. + * + * @return + */ + public static SimplTypesScope getTranslationScope() + { + return SimplTypesScope.get(PACKAGE_NAME, TRANSLATIONS); + } + /** + * @return Returns the body. + */ + public Body getBody() + { + return body; + } + /** + * @param body The body to set. + */ + public void setBody(Body body) + { + this.body = body; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/opml/Outline.java b/simplCore/src/ecologylab/serialization/library/opml/Outline.java index 32d6f576..b2144ca5 100644 --- a/simplCore/src/ecologylab/serialization/library/opml/Outline.java +++ b/simplCore/src/ecologylab/serialization/library/opml/Outline.java @@ -1,96 +1,96 @@ -/** - * - */ -package ecologylab.serialization.library.opml; - -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Nestable Outline Processor Markup Language construct. - * - * @author andruid - */ -@simpl_inherit -public class Outline extends ElementState -{ - @simpl_scalar String title; - @simpl_scalar ParsedURL xmlUrl; - @simpl_scalar ParsedURL htmlUrl; - - @simpl_collection ArrayList outline; - - /** - * - */ - public Outline() - { - super(); - } - - - /** - * @return Returns the htmlUrl. - */ - public ParsedURL getHtmlUrl() - { - return htmlUrl; - } - - - /** - * @param htmlUrl The htmlUrl to set. - */ - public void setHtmlUrl(ParsedURL htmlUrl) - { - this.htmlUrl = htmlUrl; - } - - - /** - * @return Returns the title. - */ - public String getTitle() - { - return title; - } - - - /** - * @param title The title to set. - */ - public void setTitle(String title) - { - this.title = title; - } - - - /** - * @return Returns the xmlUrl. - */ - public ParsedURL getXmlUrl() - { - return xmlUrl; - } - - - /** - * @param xmlUrl The xmlUrl to set. - */ - public void setXmlUrl(ParsedURL xmlUrl) - { - this.xmlUrl = xmlUrl; - } - - public ArrayList getOutline() { - if (outline != null) - return outline; - return outline = new ArrayList(); - } - -} +/** + * + */ +package ecologylab.serialization.library.opml; + +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Nestable Outline Processor Markup Language construct. + * + * @author andruid + */ +@simpl_inherit +public class Outline extends ElementState +{ + @simpl_scalar String title; + @simpl_scalar ParsedURL xmlUrl; + @simpl_scalar ParsedURL htmlUrl; + + @simpl_collection ArrayList outline; + + /** + * + */ + public Outline() + { + super(); + } + + + /** + * @return Returns the htmlUrl. + */ + public ParsedURL getHtmlUrl() + { + return htmlUrl; + } + + + /** + * @param htmlUrl The htmlUrl to set. + */ + public void setHtmlUrl(ParsedURL htmlUrl) + { + this.htmlUrl = htmlUrl; + } + + + /** + * @return Returns the title. + */ + public String getTitle() + { + return title; + } + + + /** + * @param title The title to set. + */ + public void setTitle(String title) + { + this.title = title; + } + + + /** + * @return Returns the xmlUrl. + */ + public ParsedURL getXmlUrl() + { + return xmlUrl; + } + + + /** + * @param xmlUrl The xmlUrl to set. + */ + public void setXmlUrl(ParsedURL xmlUrl) + { + this.xmlUrl = xmlUrl; + } + + public ArrayList getOutline() { + if (outline != null) + return outline; + return outline = new ArrayList(); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/opml/package.html b/simplCore/src/ecologylab/serialization/library/opml/package.html index 6360621a..c9d842da 100644 --- a/simplCore/src/ecologylab/serialization/library/opml/package.html +++ b/simplCore/src/ecologylab/serialization/library/opml/package.html @@ -1,5 +1,5 @@ - -Ecologylab.XML derived classes of ElementState that -implement an Outline Processor Markup Language parser. - + +Ecologylab.XML derived classes of ElementState that +implement an Outline Processor Markup Language parser. + \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/library/package.html b/simplCore/src/ecologylab/serialization/library/package.html index 6c1cb013..1ce9fd86 100644 --- a/simplCore/src/ecologylab/serialization/library/package.html +++ b/simplCore/src/ecologylab/serialization/library/package.html @@ -1,4 +1,4 @@ - -A library of ElementState subclass object used to parse (more or less) -standard forms of XML. - + +A library of ElementState subclass object used to parse (more or less) +standard forms of XML. + diff --git a/simplCore/src/ecologylab/serialization/library/rest/Fields.java b/simplCore/src/ecologylab/serialization/library/rest/Fields.java index f8c2942b..c8313f25 100644 --- a/simplCore/src/ecologylab/serialization/library/rest/Fields.java +++ b/simplCore/src/ecologylab/serialization/library/rest/Fields.java @@ -1,183 +1,183 @@ -package ecologylab.serialization.library.rest; - -import java.net.URL; - -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.library.dc.Dc; - -@simpl_inherit -public class Fields extends Dc -{ - - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String primaryIdentifier; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String category; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String compoundAgent; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String compoundGenre; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String compoundTitle; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String compoundDescription; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String compoundSubject; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String primaryCollection; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String brandTitle; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) URL brandIconURL; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) int brandWidth; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) int brandHeight; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String bestPassage; - - public Fields() - { - super(); - } - - @Override - public String toString() - { - return "Fields: {\n" + super.toString() + "\n" + - "primaryIdentifier: " + getPrimaryIdentifier() + "\n" + - "category: " + category + "\n" + - "compoundAgent: " + compoundAgent + "\n" + - "compoundGenre: " + compoundGenre + "\n" + - "compoundTitle: " + getCompoundTitle() + "\n" + - "compoundDescription: " + getCompoundDescription() + "\n" + - "compoundSubject: " + getCompoundSubject() + "\n" + - "primaryCollection: " + primaryCollection + "\n" + - "brandTitle: " + getBrandTitle() + "\n" + - "brandIconURL: " + getBrandIconURL() + "\n" + - "brandWidth: " + getBrandWidth() + "\n" + - "brandHeight: " + getBrandHeight() + "\n" + - "bestPassage: " + bestPassage + "\n" + - "}"; - - - } - - /** - * @param compoundTitle the compoundTitle to set - */ - public void setCompoundTitle(String compoundTitle) - { - this.compoundTitle = compoundTitle; - } - - /** - * @return the compoundTitle - */ - public String getCompoundTitle() - { - return compoundTitle; - } - - /** - * @param compoundDescription the compoundDescription to set - */ - public void setCompoundDescription(String compoundDescription) - { - this.compoundDescription = compoundDescription; - } - - /** - * @return the compoundDescription - */ - public String getCompoundDescription() - { - return compoundDescription; - } - - /** - * @param compoundSubject the compoundSubject to set - */ - public void setCompoundSubject(String compoundSubject) - { - this.compoundSubject = compoundSubject; - } - - /** - * @return the compoundSubject - */ - public String getCompoundSubject() - { - return compoundSubject; - } - - /** - * @param brandIconURL the brandIconURL to set - */ - public void setBrandIconURL(URL brandIconURL) - { - this.brandIconURL = brandIconURL; - } - - /** - * @return the brandIconURL - */ - public URL getBrandIconURL() - { - return brandIconURL; - } - - /** - * @param brandTitle the brandTitle to set - */ - public void setBrandTitle(String brandTitle) - { - this.brandTitle = brandTitle; - } - - /** - * @return the brandTitle - */ - public String getBrandTitle() - { - return brandTitle; - } - - /** - * @param brandWidth the brandWidth to set - */ - public void setBrandWidth(int brandWidth) - { - this.brandWidth = brandWidth; - } - - /** - * @return the brandWidth - */ - public int getBrandWidth() - { - return brandWidth; - } - - /** - * @param brandHeight the brandHeight to set - */ - public void setBrandHeight(int brandHeight) - { - this.brandHeight = brandHeight; - } - - /** - * @return the brandHeight - */ - public int getBrandHeight() - { - return brandHeight; - } - - /** - * @param primaryIdentifier the primaryIdentifier to set - */ - public void setPrimaryIdentifier(String primaryIdentifier) - { - this.primaryIdentifier = primaryIdentifier; - } - - /** - * @return the primaryIdentifier - */ - public String getPrimaryIdentifier() - { - return primaryIdentifier; - } -} +package ecologylab.serialization.library.rest; + +import java.net.URL; + +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.library.dc.Dc; + +@simpl_inherit +public class Fields extends Dc +{ + + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String primaryIdentifier; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String category; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String compoundAgent; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String compoundGenre; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String compoundTitle; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String compoundDescription; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String compoundSubject; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String primaryCollection; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String brandTitle; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) URL brandIconURL; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) int brandWidth; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) int brandHeight; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String bestPassage; + + public Fields() + { + super(); + } + + @Override + public String toString() + { + return "Fields: {\n" + super.toString() + "\n" + + "primaryIdentifier: " + getPrimaryIdentifier() + "\n" + + "category: " + category + "\n" + + "compoundAgent: " + compoundAgent + "\n" + + "compoundGenre: " + compoundGenre + "\n" + + "compoundTitle: " + getCompoundTitle() + "\n" + + "compoundDescription: " + getCompoundDescription() + "\n" + + "compoundSubject: " + getCompoundSubject() + "\n" + + "primaryCollection: " + primaryCollection + "\n" + + "brandTitle: " + getBrandTitle() + "\n" + + "brandIconURL: " + getBrandIconURL() + "\n" + + "brandWidth: " + getBrandWidth() + "\n" + + "brandHeight: " + getBrandHeight() + "\n" + + "bestPassage: " + bestPassage + "\n" + + "}"; + + + } + + /** + * @param compoundTitle the compoundTitle to set + */ + public void setCompoundTitle(String compoundTitle) + { + this.compoundTitle = compoundTitle; + } + + /** + * @return the compoundTitle + */ + public String getCompoundTitle() + { + return compoundTitle; + } + + /** + * @param compoundDescription the compoundDescription to set + */ + public void setCompoundDescription(String compoundDescription) + { + this.compoundDescription = compoundDescription; + } + + /** + * @return the compoundDescription + */ + public String getCompoundDescription() + { + return compoundDescription; + } + + /** + * @param compoundSubject the compoundSubject to set + */ + public void setCompoundSubject(String compoundSubject) + { + this.compoundSubject = compoundSubject; + } + + /** + * @return the compoundSubject + */ + public String getCompoundSubject() + { + return compoundSubject; + } + + /** + * @param brandIconURL the brandIconURL to set + */ + public void setBrandIconURL(URL brandIconURL) + { + this.brandIconURL = brandIconURL; + } + + /** + * @return the brandIconURL + */ + public URL getBrandIconURL() + { + return brandIconURL; + } + + /** + * @param brandTitle the brandTitle to set + */ + public void setBrandTitle(String brandTitle) + { + this.brandTitle = brandTitle; + } + + /** + * @return the brandTitle + */ + public String getBrandTitle() + { + return brandTitle; + } + + /** + * @param brandWidth the brandWidth to set + */ + public void setBrandWidth(int brandWidth) + { + this.brandWidth = brandWidth; + } + + /** + * @return the brandWidth + */ + public int getBrandWidth() + { + return brandWidth; + } + + /** + * @param brandHeight the brandHeight to set + */ + public void setBrandHeight(int brandHeight) + { + this.brandHeight = brandHeight; + } + + /** + * @return the brandHeight + */ + public int getBrandHeight() + { + return brandHeight; + } + + /** + * @param primaryIdentifier the primaryIdentifier to set + */ + public void setPrimaryIdentifier(String primaryIdentifier) + { + this.primaryIdentifier = primaryIdentifier; + } + + /** + * @return the primaryIdentifier + */ + public String getPrimaryIdentifier() + { + return primaryIdentifier; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/rest/Header.java b/simplCore/src/ecologylab/serialization/library/rest/Header.java index fe82c756..44a6d9c6 100644 --- a/simplCore/src/ecologylab/serialization/library/rest/Header.java +++ b/simplCore/src/ecologylab/serialization/library/rest/Header.java @@ -1,27 +1,27 @@ -package ecologylab.serialization.library.rest; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; - -public class Header extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String identifier; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String lastIndexed; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String metadataLastModified; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String contentLastModified; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String contentLastFetched; - - public Header() {} - - public Header(String identifier, String lastIndexed, String metadataLastModified, - String contentLastModified, String contentLastFetched) - { - this.identifier = identifier; - this.lastIndexed = lastIndexed; - this.metadataLastModified = metadataLastModified; - this.contentLastModified = contentLastModified; - this.contentLastFetched = contentLastFetched; - } -} +package ecologylab.serialization.library.rest; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; + +public class Header extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String identifier; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String lastIndexed; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String metadataLastModified; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String contentLastModified; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String contentLastFetched; + + public Header() {} + + public Header(String identifier, String lastIndexed, String metadataLastModified, + String contentLastModified, String contentLastFetched) + { + this.identifier = identifier; + this.lastIndexed = lastIndexed; + this.metadataLastModified = metadataLastModified; + this.contentLastModified = contentLastModified; + this.contentLastFetched = contentLastFetched; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/rest/RESTTranslationSpace.java b/simplCore/src/ecologylab/serialization/library/rest/RESTTranslationSpace.java index 65ee3f72..6ec32f30 100644 --- a/simplCore/src/ecologylab/serialization/library/rest/RESTTranslationSpace.java +++ b/simplCore/src/ecologylab/serialization/library/rest/RESTTranslationSpace.java @@ -1,25 +1,25 @@ -package ecologylab.serialization.library.rest; - -import ecologylab.generic.Debug; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.library.dc.Dc; - -public class RESTTranslationSpace extends Debug -{ - public static final String NAME = "ecologylab.serialization.library.rest"; - public static final String PACKAGE_NAME = "ecologylab.serialization.library.rest"; - - protected static final Class TRANSLATIONS[] = - { - RestSearchResult.class, - SearchResults.class, - Record.class - }; - - protected static final SimplTypesScope INHERITED[] = {Dc.get()}; - - public static SimplTypesScope get() - { - return SimplTypesScope.get(PACKAGE_NAME, INHERITED, TRANSLATIONS); - } -} +package ecologylab.serialization.library.rest; + +import ecologylab.generic.Debug; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.library.dc.Dc; + +public class RESTTranslationSpace extends Debug +{ + public static final String NAME = "ecologylab.serialization.library.rest"; + public static final String PACKAGE_NAME = "ecologylab.serialization.library.rest"; + + protected static final Class TRANSLATIONS[] = + { + RestSearchResult.class, + SearchResults.class, + Record.class + }; + + protected static final SimplTypesScope INHERITED[] = {Dc.get()}; + + public static SimplTypesScope get() + { + return SimplTypesScope.get(PACKAGE_NAME, INHERITED, TRANSLATIONS); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/rest/Record.java b/simplCore/src/ecologylab/serialization/library/rest/Record.java index a342b984..332b8ae8 100644 --- a/simplCore/src/ecologylab/serialization/library/rest/Record.java +++ b/simplCore/src/ecologylab/serialization/library/rest/Record.java @@ -1,40 +1,40 @@ -package ecologylab.serialization.library.rest; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; - -public class Record extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected int position; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected double score; - @simpl_composite protected Header header; - @simpl_composite protected Fields fields; - - public Record() {} - - public Record(int position, double score, Header header, Fields fields) - { - this.position = position; - this.score = score; - this.header = header; - this.fields = fields; - } - - /** - * @param fields the fields to set - */ - public void setFields(Fields fields) - { - this.fields = fields; - } - /** - * @return the fields - */ - public Fields getFields() - { - return fields; - } -} +package ecologylab.serialization.library.rest; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; + +public class Record extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected int position; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected double score; + @simpl_composite protected Header header; + @simpl_composite protected Fields fields; + + public Record() {} + + public Record(int position, double score, Header header, Fields fields) + { + this.position = position; + this.score = score; + this.header = header; + this.fields = fields; + } + + /** + * @param fields the fields to set + */ + public void setFields(Fields fields) + { + this.fields = fields; + } + /** + * @return the fields + */ + public Fields getFields() + { + return fields; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/rest/RestSearchResult.java b/simplCore/src/ecologylab/serialization/library/rest/RestSearchResult.java index 9b695672..d8bd9a8a 100644 --- a/simplCore/src/ecologylab/serialization/library/rest/RestSearchResult.java +++ b/simplCore/src/ecologylab/serialization/library/rest/RestSearchResult.java @@ -1,119 +1,119 @@ -package ecologylab.serialization.library.rest; - -import java.net.URL; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * Rest Search Results - * @author blake - * - */ -public class RestSearchResult extends ElementState -{ - @simpl_scalar protected String schemaVersion; - @simpl_scalar protected String xmlns; - @simpl_scalar @simpl_tag("xmlns:xsi") - protected String xsi = "http://www.w3.org/2001/XMLSchema-instance"; - @simpl_scalar @simpl_tag("xmlns:dc") - protected String dc = "http://purl.org/dc/elements/1.1/"; - @simpl_scalar @simpl_tag("xsi:schemaLocation") - protected String schemaLocation; - - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String responseTime; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected URL request; - @simpl_composite @simpl_tag("SearchResults") - protected SearchResults SearchResults; - - public RestSearchResult() {} - - /** - * @param schemaVersion the schemaVersion to set - */ - public void setSchemaVersion(String schemaVersion) - { - this.schemaVersion = schemaVersion; - } - - /** - * @return the schemaVersion - */ - public String getSchemaVersion() - { - return schemaVersion; - } - - /** - * @param xmlns the xmlns to set - */ - public void setXmlns(String xmlns) - { - this.xmlns = xmlns; - } - - /** - * @return the xmlns - */ - public String getXmlns() - { - return xmlns; - } - - /** - * @param searchResults the searchResults to set - */ - public void setSearchResults(SearchResults searchResults) - { - this.SearchResults = searchResults; - } - - /** - * @return the searchResults - */ - public SearchResults getSearchResults() - { - return SearchResults; - } - - @Override - public String toString() - { - return "RestSearchResult{\n" + - "responseTime: " + responseTime + "\n" + - "request: " + getRequest() + "\n" + - "SearchResults: " + SearchResults + "\n" + - "}"; - } - - public void setRequest(URL request) - { - this.request = request; - } - - public URL getRequest() - { - return request; - } - - /** - * @param schemaLocation the schemaLocation to set - */ - public void setSchemaLocation(String schemaLocation) - { - this.schemaLocation = schemaLocation; - } - - /** - * @return the schemaLocation - */ - public String getSchemaLocation() - { - return schemaLocation; - } - -} +package ecologylab.serialization.library.rest; + +import java.net.URL; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * Rest Search Results + * @author blake + * + */ +public class RestSearchResult extends ElementState +{ + @simpl_scalar protected String schemaVersion; + @simpl_scalar protected String xmlns; + @simpl_scalar @simpl_tag("xmlns:xsi") + protected String xsi = "http://www.w3.org/2001/XMLSchema-instance"; + @simpl_scalar @simpl_tag("xmlns:dc") + protected String dc = "http://purl.org/dc/elements/1.1/"; + @simpl_scalar @simpl_tag("xsi:schemaLocation") + protected String schemaLocation; + + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected String responseTime; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected URL request; + @simpl_composite @simpl_tag("SearchResults") + protected SearchResults SearchResults; + + public RestSearchResult() {} + + /** + * @param schemaVersion the schemaVersion to set + */ + public void setSchemaVersion(String schemaVersion) + { + this.schemaVersion = schemaVersion; + } + + /** + * @return the schemaVersion + */ + public String getSchemaVersion() + { + return schemaVersion; + } + + /** + * @param xmlns the xmlns to set + */ + public void setXmlns(String xmlns) + { + this.xmlns = xmlns; + } + + /** + * @return the xmlns + */ + public String getXmlns() + { + return xmlns; + } + + /** + * @param searchResults the searchResults to set + */ + public void setSearchResults(SearchResults searchResults) + { + this.SearchResults = searchResults; + } + + /** + * @return the searchResults + */ + public SearchResults getSearchResults() + { + return SearchResults; + } + + @Override + public String toString() + { + return "RestSearchResult{\n" + + "responseTime: " + responseTime + "\n" + + "request: " + getRequest() + "\n" + + "SearchResults: " + SearchResults + "\n" + + "}"; + } + + public void setRequest(URL request) + { + this.request = request; + } + + public URL getRequest() + { + return request; + } + + /** + * @param schemaLocation the schemaLocation to set + */ + public void setSchemaLocation(String schemaLocation) + { + this.schemaLocation = schemaLocation; + } + + /** + * @return the schemaLocation + */ + public String getSchemaLocation() + { + return schemaLocation; + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/rest/ResultsInfo.java b/simplCore/src/ecologylab/serialization/library/rest/ResultsInfo.java index 5e7b77a6..3cf4fb0d 100644 --- a/simplCore/src/ecologylab/serialization/library/rest/ResultsInfo.java +++ b/simplCore/src/ecologylab/serialization/library/rest/ResultsInfo.java @@ -1,70 +1,70 @@ -package ecologylab.serialization.library.rest; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; - -public class ResultsInfo extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected int totalNumResults; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected int numSkipped; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected int numReturned; - - public ResultsInfo() {} - - public ResultsInfo(int totalNumResults, int numSkipped, int numReturned) - { - this.setTotalNumResults(totalNumResults); - this.setNumSkipped(numSkipped); - this.setNumReturned(numReturned); - } - - /** - * @param totalNumResults the totalNumResults to set - */ - public void setTotalNumResults(int totalNumResults) - { - this.totalNumResults = totalNumResults; - } - - /** - * @return the totalNumResults - */ - public int getTotalNumResults() - { - return totalNumResults; - } - - /** - * @param numSkipped the numSkipped to set - */ - public void setNumSkipped(int numSkipped) - { - this.numSkipped = numSkipped; - } - - /** - * @return the numSkipped - */ - public int getNumSkipped() - { - return numSkipped; - } - - /** - * @param numReturned the numReturned to set - */ - public void setNumReturned(int numReturned) - { - this.numReturned = numReturned; - } - - /** - * @return the numReturned - */ - public int getNumReturned() - { - return numReturned; - } -} +package ecologylab.serialization.library.rest; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; + +public class ResultsInfo extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected int totalNumResults; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected int numSkipped; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) protected int numReturned; + + public ResultsInfo() {} + + public ResultsInfo(int totalNumResults, int numSkipped, int numReturned) + { + this.setTotalNumResults(totalNumResults); + this.setNumSkipped(numSkipped); + this.setNumReturned(numReturned); + } + + /** + * @param totalNumResults the totalNumResults to set + */ + public void setTotalNumResults(int totalNumResults) + { + this.totalNumResults = totalNumResults; + } + + /** + * @return the totalNumResults + */ + public int getTotalNumResults() + { + return totalNumResults; + } + + /** + * @param numSkipped the numSkipped to set + */ + public void setNumSkipped(int numSkipped) + { + this.numSkipped = numSkipped; + } + + /** + * @return the numSkipped + */ + public int getNumSkipped() + { + return numSkipped; + } + + /** + * @param numReturned the numReturned to set + */ + public void setNumReturned(int numReturned) + { + this.numReturned = numReturned; + } + + /** + * @return the numReturned + */ + public int getNumReturned() + { + return numReturned; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/rest/SearchResults.java b/simplCore/src/ecologylab/serialization/library/rest/SearchResults.java index 0e2fe992..59fac74a 100644 --- a/simplCore/src/ecologylab/serialization/library/rest/SearchResults.java +++ b/simplCore/src/ecologylab/serialization/library/rest/SearchResults.java @@ -1,46 +1,46 @@ -package ecologylab.serialization.library.rest; - -import java.util.ArrayList; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_nowrap; - -/** - * Represents REST search results - * @author blake - * - */ -public class SearchResults extends ElementState -{ - @simpl_composite protected ResultsInfo resultsInfo; - - @simpl_nowrap - @simpl_collection("Record") - protected ArrayList results = new ArrayList(); - - public SearchResults() {} - - public SearchResults(ResultsInfo resultsInfo, ArrayList results) - { - this.resultsInfo = resultsInfo; - this.results = results; - } - - /** - * @param results the results to set - */ - public void setResults(ArrayList results) - { - this.results = results; - } - - /** - * @return the results - */ - public ArrayList getResults() - { - return results; - } -} +package ecologylab.serialization.library.rest; + +import java.util.ArrayList; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_nowrap; + +/** + * Represents REST search results + * @author blake + * + */ +public class SearchResults extends ElementState +{ + @simpl_composite protected ResultsInfo resultsInfo; + + @simpl_nowrap + @simpl_collection("Record") + protected ArrayList results = new ArrayList(); + + public SearchResults() {} + + public SearchResults(ResultsInfo resultsInfo, ArrayList results) + { + this.resultsInfo = resultsInfo; + this.results = results; + } + + /** + * @param results the results to set + */ + public void setResults(ArrayList results) + { + this.results = results; + } + + /** + * @return the results + */ + public ArrayList getResults() + { + return results; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/rest/nsdl/NSDLSearchService.java b/simplCore/src/ecologylab/serialization/library/rest/nsdl/NSDLSearchService.java index 74ea2e07..2ff26e34 100644 --- a/simplCore/src/ecologylab/serialization/library/rest/nsdl/NSDLSearchService.java +++ b/simplCore/src/ecologylab/serialization/library/rest/nsdl/NSDLSearchService.java @@ -1,19 +1,19 @@ -package ecologylab.serialization.library.rest.nsdl; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.library.rest.RestSearchResult; - -/** - * NSDL search REST wrapper. - * @author blake - * - */ -@simpl_inherit @simpl_tag("NSDLSearchService") -public class NSDLSearchService extends RestSearchResult -{ - public NSDLSearchService() - { - super(); - } -} +package ecologylab.serialization.library.rest.nsdl; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.library.rest.RestSearchResult; + +/** + * NSDL search REST wrapper. + * @author blake + * + */ +@simpl_inherit @simpl_tag("NSDLSearchService") +public class NSDLSearchService extends RestSearchResult +{ + public NSDLSearchService() + { + super(); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/rest/nsdl/NSDLTranslationSpace.java b/simplCore/src/ecologylab/serialization/library/rest/nsdl/NSDLTranslationSpace.java index 608b8457..b146ad1b 100644 --- a/simplCore/src/ecologylab/serialization/library/rest/nsdl/NSDLTranslationSpace.java +++ b/simplCore/src/ecologylab/serialization/library/rest/nsdl/NSDLTranslationSpace.java @@ -1,24 +1,24 @@ -package ecologylab.serialization.library.rest.nsdl; - -import ecologylab.generic.Debug; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.library.rest.RESTTranslationSpace; -import ecologylab.serialization.library.rest.SearchResults; - -public class NSDLTranslationSpace extends Debug -{ - public static final String PACKAGE_NAME = "ecologylab.serialization.library.rest.nsdl"; - - protected static final Class TRANSLATIONS[] = - { - NSDLSearchService.class, - SearchResults.class - }; - - protected static final SimplTypesScope INHERITED[]= {RESTTranslationSpace.get()}; - - public static SimplTypesScope get() - { - return SimplTypesScope.get(PACKAGE_NAME, INHERITED, TRANSLATIONS); - } -} +package ecologylab.serialization.library.rest.nsdl; + +import ecologylab.generic.Debug; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.library.rest.RESTTranslationSpace; +import ecologylab.serialization.library.rest.SearchResults; + +public class NSDLTranslationSpace extends Debug +{ + public static final String PACKAGE_NAME = "ecologylab.serialization.library.rest.nsdl"; + + protected static final Class TRANSLATIONS[] = + { + NSDLSearchService.class, + SearchResults.class + }; + + protected static final SimplTypesScope INHERITED[]= {RESTTranslationSpace.get()}; + + public static SimplTypesScope get() + { + return SimplTypesScope.get(PACKAGE_NAME, INHERITED, TRANSLATIONS); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/rss/Channel.java b/simplCore/src/ecologylab/serialization/library/rss/Channel.java index 998f9db6..bc105e4d 100644 --- a/simplCore/src/ecologylab/serialization/library/rss/Channel.java +++ b/simplCore/src/ecologylab/serialization/library/rss/Channel.java @@ -1,154 +1,154 @@ -package ecologylab.serialization.library.rss; - -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * RSS parser channel element {@link ecologylab.serialization.ElementState - * ElementState} declaration. Used with most RSS versions. - * - * @author andruid - */ -public @simpl_inherit -class Channel extends ElementState -{ - @simpl_scalar - @simpl_hints(Hint.XML_LEAF) - String title; - - @simpl_scalar - @simpl_hints(Hint.XML_LEAF) - String description; - - /** - * Could point to an HTML rendering of the feed. - */ - @simpl_scalar - @simpl_hints(Hint.XML_LEAF) - ParsedURL link; - - @simpl_nowrap - @simpl_collection("item") - ArrayList items; - - /** - * @return Returns the description. - */ - public String getDescription() - { - return description; - } - - /** - * @param description - * The description to set. - */ - public void setDescription(String description) - { - this.description = description; - } - - /** - * @return Returns the title. - */ - public String getTitle() - { - return title; - } - - /** - * @param title - * The title to set. - */ - public void setTitle(String title) - { - this.title = title; - } - - /** - * @return Returns the link. - */ - public ParsedURL getLink() - { - return link; - } - - /** - * @param link - * The link to set. - */ - public void setLink(ParsedURL link) - { - this.link = link; - } - - public ArrayList getItems() - { - return items; - } - - public void add(Item item) - { - if (items == null) - items = new ArrayList(); - items.add(item); - } - - public Item get(int i) - { - return items == null ? null : items.get(i); - } - - public int size() - { - return items == null ? 0 : items.size(); - } - - public static void main(String[] s) - { - testTranslateTo(); - } - - private static void testTranslateTo() - { - Channel c = new Channel(); - Item i1 = new Item(); - i1.author = "zach"; - i1.title = "it is called rogue!"; - i1.link = ParsedURL.getAbsolute("http://ecologylab.cs.tamu.edu/rogue/"); - i1.description = "its a game"; - Item i2 = new Item(); - i2.author = "andruid"; - i2.title = "it is called cf!"; - i2.description = "its a creativity support tool"; - c.items = new ArrayList(); - c.items.add(i1); - c.items.add(i2); - try - { - StringBuilder buffy = new StringBuilder(); - SimplTypesScope.serialize(c, buffy, StringFormat.XML); - System.out.println(buffy); - System.out.println('\n'); - ElementState c2 = (ElementState) RssTranslations.get().deserialize(buffy, StringFormat.XML); - SimplTypesScope.serialize(c2, System.out, StringFormat.XML); - // println(c.translateToXML()); - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } -} +package ecologylab.serialization.library.rss; + +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * RSS parser channel element {@link ecologylab.serialization.ElementState + * ElementState} declaration. Used with most RSS versions. + * + * @author andruid + */ +public @simpl_inherit +class Channel extends ElementState +{ + @simpl_scalar + @simpl_hints(Hint.XML_LEAF) + String title; + + @simpl_scalar + @simpl_hints(Hint.XML_LEAF) + String description; + + /** + * Could point to an HTML rendering of the feed. + */ + @simpl_scalar + @simpl_hints(Hint.XML_LEAF) + ParsedURL link; + + @simpl_nowrap + @simpl_collection("item") + ArrayList items; + + /** + * @return Returns the description. + */ + public String getDescription() + { + return description; + } + + /** + * @param description + * The description to set. + */ + public void setDescription(String description) + { + this.description = description; + } + + /** + * @return Returns the title. + */ + public String getTitle() + { + return title; + } + + /** + * @param title + * The title to set. + */ + public void setTitle(String title) + { + this.title = title; + } + + /** + * @return Returns the link. + */ + public ParsedURL getLink() + { + return link; + } + + /** + * @param link + * The link to set. + */ + public void setLink(ParsedURL link) + { + this.link = link; + } + + public ArrayList getItems() + { + return items; + } + + public void add(Item item) + { + if (items == null) + items = new ArrayList(); + items.add(item); + } + + public Item get(int i) + { + return items == null ? null : items.get(i); + } + + public int size() + { + return items == null ? 0 : items.size(); + } + + public static void main(String[] s) + { + testTranslateTo(); + } + + private static void testTranslateTo() + { + Channel c = new Channel(); + Item i1 = new Item(); + i1.author = "zach"; + i1.title = "it is called rogue!"; + i1.link = ParsedURL.getAbsolute("http://ecologylab.cs.tamu.edu/rogue/"); + i1.description = "its a game"; + Item i2 = new Item(); + i2.author = "andruid"; + i2.title = "it is called cf!"; + i2.description = "its a creativity support tool"; + c.items = new ArrayList(); + c.items.add(i1); + c.items.add(i2); + try + { + StringBuilder buffy = new StringBuilder(); + SimplTypesScope.serialize(c, buffy, StringFormat.XML); + System.out.println(buffy); + System.out.println('\n'); + ElementState c2 = (ElementState) RssTranslations.get().deserialize(buffy, StringFormat.XML); + SimplTypesScope.serialize(c2, System.out, StringFormat.XML); + // println(c.translateToXML()); + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/simplCore/src/ecologylab/serialization/library/rss/Channel2.java b/simplCore/src/ecologylab/serialization/library/rss/Channel2.java index 1a671241..086491a9 100644 --- a/simplCore/src/ecologylab/serialization/library/rss/Channel2.java +++ b/simplCore/src/ecologylab/serialization/library/rss/Channel2.java @@ -1,151 +1,151 @@ -package ecologylab.serialization.library.rss; - -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * RSS parser channel element {@link ecologylab.serialization.ElementState - * ElementState} declaration. Used with most RSS versions. - * - * @author andruid - */ -public @simpl_inherit -class Channel2 extends ElementState // ArrayListState -{ - @simpl_scalar - @simpl_hints(Hint.XML_LEAF) - String title; - - @simpl_scalar - @simpl_hints(Hint.XML_LEAF) - String description; - - /** - * Could point to an HTML rendering of the feed. - */ - @simpl_scalar - @simpl_hints(Hint.XML_LEAF) - ParsedURL link; - - @simpl_nowrap - @simpl_collection("item") - ArrayList items; // = new ArrayList(); - - /** - * @return Returns the description. - */ - public String getDescription() - { - return description; - } - - /** - * @param description - * The description to set. - */ - public void setDescription(String description) - { - this.description = description; - } - - /** - * @return Returns the title. - */ - public String getTitle() - { - return title; - } - - /** - * @param title - * The title to set. - */ - public void setTitle(String title) - { - this.title = title; - } - - /** - * @return Returns the link. - */ - public ParsedURL getLink() - { - return link; - } - - /** - * @param link - * The link to set. - */ - public void setLink(ParsedURL link) - { - this.link = link; - } - - public ArrayList getItems() - { - return items; - } - - public void setItems(ArrayList items) - { - this.items = items; - } - - public int size() - { - return items == null ? 0 : items.size(); - } - - public Item get(int i) - { - return items == null ? null : items.get(i); - } - - // @Override - // protected Collection getCollection(Class thatClass) - // { - // return items; - // } - - public static void main(String[] s) - { - Channel2 c = new Channel2(); - Item i1 = new Item(); - i1.author = "zach"; - i1.title = "it is called rogue!"; - i1.link = ParsedURL.getAbsolute("http://ecologylab.cs.tamu.edu/rogue/"); - i1.description = "its a game"; - Item i2 = new Item(); - i2.author = "andruid"; - i2.title = "it is called cf!"; - i2.description = "its a creativity support tool"; - c.items = new ArrayList(); - c.items.add(i1); - c.items.add(i2); - // c.add(i1); - // c.add(i2); - try - { - - SimplTypesScope.serialize(c, System.out, StringFormat.XML); - - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } -} +package ecologylab.serialization.library.rss; + +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * RSS parser channel element {@link ecologylab.serialization.ElementState + * ElementState} declaration. Used with most RSS versions. + * + * @author andruid + */ +public @simpl_inherit +class Channel2 extends ElementState // ArrayListState +{ + @simpl_scalar + @simpl_hints(Hint.XML_LEAF) + String title; + + @simpl_scalar + @simpl_hints(Hint.XML_LEAF) + String description; + + /** + * Could point to an HTML rendering of the feed. + */ + @simpl_scalar + @simpl_hints(Hint.XML_LEAF) + ParsedURL link; + + @simpl_nowrap + @simpl_collection("item") + ArrayList items; // = new ArrayList(); + + /** + * @return Returns the description. + */ + public String getDescription() + { + return description; + } + + /** + * @param description + * The description to set. + */ + public void setDescription(String description) + { + this.description = description; + } + + /** + * @return Returns the title. + */ + public String getTitle() + { + return title; + } + + /** + * @param title + * The title to set. + */ + public void setTitle(String title) + { + this.title = title; + } + + /** + * @return Returns the link. + */ + public ParsedURL getLink() + { + return link; + } + + /** + * @param link + * The link to set. + */ + public void setLink(ParsedURL link) + { + this.link = link; + } + + public ArrayList getItems() + { + return items; + } + + public void setItems(ArrayList items) + { + this.items = items; + } + + public int size() + { + return items == null ? 0 : items.size(); + } + + public Item get(int i) + { + return items == null ? null : items.get(i); + } + + // @Override + // protected Collection getCollection(Class thatClass) + // { + // return items; + // } + + public static void main(String[] s) + { + Channel2 c = new Channel2(); + Item i1 = new Item(); + i1.author = "zach"; + i1.title = "it is called rogue!"; + i1.link = ParsedURL.getAbsolute("http://ecologylab.cs.tamu.edu/rogue/"); + i1.description = "its a game"; + Item i2 = new Item(); + i2.author = "andruid"; + i2.title = "it is called cf!"; + i2.description = "its a creativity support tool"; + c.items = new ArrayList(); + c.items.add(i1); + c.items.add(i2); + // c.add(i1); + // c.add(i2); + try + { + + SimplTypesScope.serialize(c, System.out, StringFormat.XML); + + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/simplCore/src/ecologylab/serialization/library/rss/Item.java b/simplCore/src/ecologylab/serialization/library/rss/Item.java index 31081a48..8b54bf4e 100644 --- a/simplCore/src/ecologylab/serialization/library/rss/Item.java +++ b/simplCore/src/ecologylab/serialization/library/rss/Item.java @@ -1,182 +1,182 @@ -package ecologylab.serialization.library.rss; - -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * RSS parser ite element {@link ecologylab.serialization.ElementState ElementState} declaration. - * Used with most (perhaps all) RSS versions. - *

- * Includes support for funky included namespace content, such as DublinCore, Yahoo Media, and Feedburner. - * - * @author andruid - */ -public class Item extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; - /** - * This version of link often has a special url with rss in it. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; - /** - * This seems to be the version of link that users want to see. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL guid; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String author; - - @simpl_nowrap - @simpl_collection("category") ArrayList categorySet; - - public Item() - { - super(); - } - public Item(String title) - { - super(); - this.title = title; - } - /** - * @return Returns the author. - */ - public String getAuthor() - { - return author; - } - - /** - * @param author The author to set. - */ - public void setAuthor(String author) - { - this.author = author; - } - - /** - * @return Returns the description. - */ - public String getDescription() - { - return description; - } - - /** - * @param description The description to set. - */ - public void setDescription(String description) - { - this.description = description; - } - - /** - * @return Returns the link. - */ - public ParsedURL getLink() - { - return link; - } - - /** - * @param link The link to set. - */ - public void setLink(ParsedURL link) - { - this.link = link; - } - - /** - * @return Returns the title. - */ - public String getTitle() - { - return title; - } - - /** - * @param title The title to set. - */ - public void setTitle(String title) - { - this.title = title; - } - -// /** -// * Some people put Dublin Core fields into their items. Go figure :-) -// *

-// * Lookup a NestedNameSpace element child of this, in case there is one, -// * declared as xmlns:dc. -// * (Example: del.icio.us) -// * -// * @return Returns the Dc nested namespace element, or null.. -// */ -// public Dc lookupDc() -// { -// return (Dc) lookupNestedNameSpace("dc"); -// } -// -// /** -// * Lookup a NestedNameSpace element child of this, in case there is one, -// * declared as xmlns:media. -// * Yahoo Media metadata declarations. -// * -// * @return Returns the Media nested namespace element, or null.. -// */ -// public Media lookupMedia() -// { -// return (Media) lookupNestedNameSpace("media"); -// } -// -// -// /** -// * Lookup a NestedNameSpace element child of this, in case there is one, -// * declared as xmlns:feedburner. -// * -// * @return Returns the Feedburner nested namespace element, or null.. -// */ -// public Feedburner lookupFeedburner() -// { -// return (Feedburner) lookupNestedNameSpace("feedburner"); - // } - -// /** -// * If there is an embedded object handling the feedburner namespace, get the origLink -// * leaf_node from it. -// * -// * @return -// */ -// public ParsedURL getFeedburnerOrigLink() -// { -// Feedburner feedburner = lookupFeedburner(); -// return (feedburner == null) ? null : feedburner.getOrigLink(); -// } -// -// public ParsedURL getDcIdentifier() -// { -// Dc dc = lookupDc(); -// return (dc == null) ? null : dc.getIdentifier(); -// } - -// /** -// * Get what looks like the most direct form of the link URL. -// * -// * @return -// */ -// public ParsedURL getDirectLink() -// { -// ParsedURL result = guid; -// if (result == null) -// result = getFeedburnerOrigLink(); -// if (result == null) -// result = getDcIdentifier(); -// -// return (result != null) ? result : link; -// } -} +package ecologylab.serialization.library.rss; + +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * RSS parser ite element {@link ecologylab.serialization.ElementState ElementState} declaration. + * Used with most (perhaps all) RSS versions. + *

+ * Includes support for funky included namespace content, such as DublinCore, Yahoo Media, and Feedburner. + * + * @author andruid + */ +public class Item extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; + /** + * This version of link often has a special url with rss in it. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; + /** + * This seems to be the version of link that users want to see. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL guid; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String author; + + @simpl_nowrap + @simpl_collection("category") ArrayList categorySet; + + public Item() + { + super(); + } + public Item(String title) + { + super(); + this.title = title; + } + /** + * @return Returns the author. + */ + public String getAuthor() + { + return author; + } + + /** + * @param author The author to set. + */ + public void setAuthor(String author) + { + this.author = author; + } + + /** + * @return Returns the description. + */ + public String getDescription() + { + return description; + } + + /** + * @param description The description to set. + */ + public void setDescription(String description) + { + this.description = description; + } + + /** + * @return Returns the link. + */ + public ParsedURL getLink() + { + return link; + } + + /** + * @param link The link to set. + */ + public void setLink(ParsedURL link) + { + this.link = link; + } + + /** + * @return Returns the title. + */ + public String getTitle() + { + return title; + } + + /** + * @param title The title to set. + */ + public void setTitle(String title) + { + this.title = title; + } + +// /** +// * Some people put Dublin Core fields into their items. Go figure :-) +// *

+// * Lookup a NestedNameSpace element child of this, in case there is one, +// * declared as xmlns:dc. +// * (Example: del.icio.us) +// * +// * @return Returns the Dc nested namespace element, or null.. +// */ +// public Dc lookupDc() +// { +// return (Dc) lookupNestedNameSpace("dc"); +// } +// +// /** +// * Lookup a NestedNameSpace element child of this, in case there is one, +// * declared as xmlns:media. +// * Yahoo Media metadata declarations. +// * +// * @return Returns the Media nested namespace element, or null.. +// */ +// public Media lookupMedia() +// { +// return (Media) lookupNestedNameSpace("media"); +// } +// +// +// /** +// * Lookup a NestedNameSpace element child of this, in case there is one, +// * declared as xmlns:feedburner. +// * +// * @return Returns the Feedburner nested namespace element, or null.. +// */ +// public Feedburner lookupFeedburner() +// { +// return (Feedburner) lookupNestedNameSpace("feedburner"); + // } + +// /** +// * If there is an embedded object handling the feedburner namespace, get the origLink +// * leaf_node from it. +// * +// * @return +// */ +// public ParsedURL getFeedburnerOrigLink() +// { +// Feedburner feedburner = lookupFeedburner(); +// return (feedburner == null) ? null : feedburner.getOrigLink(); +// } +// +// public ParsedURL getDcIdentifier() +// { +// Dc dc = lookupDc(); +// return (dc == null) ? null : dc.getIdentifier(); +// } + +// /** +// * Get what looks like the most direct form of the link URL. +// * +// * @return +// */ +// public ParsedURL getDirectLink() +// { +// ParsedURL result = guid; +// if (result == null) +// result = getFeedburnerOrigLink(); +// if (result == null) +// result = getDcIdentifier(); +// +// return (result != null) ? result : link; +// } +} diff --git a/simplCore/src/ecologylab/serialization/library/rss/Makefile b/simplCore/src/ecologylab/serialization/library/rss/Makefile index 134f18d9..331823c4 100644 --- a/simplCore/src/ecologylab/serialization/library/rss/Makefile +++ b/simplCore/src/ecologylab/serialization/library/rss/Makefile @@ -1,16 +1,16 @@ -# current working directory -DIR = ecologylab/xml/rss - -JAVA_SRC = RssState.java Channel.java Item.java - -JAVA_ROOT= ../../../ - -MAKE_DIR = ../../../../../makefiles -include $(MAKE_DIR)/applets.make - -cabsign: all - -nsjar: all - -sunjar: all - +# current working directory +DIR = ecologylab/xml/rss + +JAVA_SRC = RssState.java Channel.java Item.java + +JAVA_ROOT= ../../../ + +MAKE_DIR = ../../../../../makefiles +include $(MAKE_DIR)/applets.make + +cabsign: all + +nsjar: all + +sunjar: all + diff --git a/simplCore/src/ecologylab/serialization/library/rss/NewFile.xml b/simplCore/src/ecologylab/serialization/library/rss/NewFile.xml index 72748563..04d200a7 100644 --- a/simplCore/src/ecologylab/serialization/library/rss/NewFile.xml +++ b/simplCore/src/ecologylab/serialization/library/rss/NewFile.xml @@ -1,37 +1,37 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/library/rss/RDFState.java b/simplCore/src/ecologylab/serialization/library/rss/RDFState.java index 9bb8b47c..d3a220e1 100644 --- a/simplCore/src/ecologylab/serialization/library/rss/RDFState.java +++ b/simplCore/src/ecologylab/serialization/library/rss/RDFState.java @@ -1,178 +1,178 @@ -package ecologylab.serialization.library.rss; - -import java.io.File; -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * Alternative root element {@link ecologylab.serialization.ElementState ElementState} declarations - * for RSS parser: that nasty RSS versions: .90 and 1.0. - *

- * This is a bit of a hack, in that it makes no attempt to handle general RDF, or to support - * namespace definitions with great depth. - *

- * Those things can be done with this framework. One of these days, an application will drive - * someone to develop such extensions. - * - * @author andruid - */ -// @xml_inherit -@simpl_tag("rdf:RDF") -public class RDFState extends ElementState // ArrayListState -{ - @simpl_nowrap - @simpl_collection("item") - ArrayList items; - - public RDFState() - { - super(); - } - - public int size() - { - return (items == null) ? 0 : items.size(); - } - - /** - * Get Item elements associated with a feed. - * - * @param i - * Index of the item in this collection. - * @return The ith Item object directly collected in this, or null if there are no Items. - */ - public Item get(int i) - { - return items == null ? null : items.get(i); - } - - // protected Collection getCollection(Class thatClass) - // { - // return Item.class.equals(thatClass) ? - // super.getCollection(thatClass) : null; - // } - - static final String DELICIOUS_EXAMPLE = "\r\n" - + "\r\n" - + "\r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + "\r\n" - + "\r\n" - + "\r\n" - + "\r\n" - + "Java Pro Online - Output Namespace-Aware XML Documents\r\n" - + "http://209.85.165.104/search?q=cache:hQMa26l1za0J:www.ftponline.com/javapro/2003_06/online/namespace_kjones_06_23_03/+namespace+declaration+java+xml&hl=en&ct=clnk&cd=4&gl=us&client=firefox-a\r\n" - + "\r\n" - + ".createElementNS\r\n" - + "andruid\r\n" - + "2007-11-19T05:56:11Z\r\n" - + "ecologylab java namespace xml\r\n" - + "\r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" + "\r\n" - + "\r\n" + "\r\n" + ""; - - static final ParsedURL DELICIOUS_POPULAR = ParsedURL - .getAbsolute("http://del.icio.us/rss/popular/"); - - public static final ParsedURL DELICIOUS_FEED = ParsedURL - .getAbsolute("http://del.icio.us/rss/andruid/"); - - public static final File outputFile = new File("/temp/rss.xml"); - - public static void main(String[] args) - { - // ElementState.setUseDOMForTranslateTo(true); - try - { - // ParsedURL feedPURL = CNN_TOP_FEED; - ParsedURL feedPURL = DELICIOUS_FEED; // DELICIOUS_POPULAR; - println("Translating RSS feed: " + feedPURL + "\n"); - - RDFState rdfState = (RDFState) RssTranslations.get().deserialize(feedPURL, Format.XML); - // RDFState rdfState = (RDFState) ElementState.translateFromXMLCharSequence(DELICIOUS_EXAMPLE, - // RssTranslations.get()); - - ArrayList items = rdfState.items; // rssState.getChannel().getItems(); - println("items: " + rdfState.size()); - if (items != null) - { - for (Item item : items) - { - println("description:\t" + item.description); - // FIXME! -- how do we make sure the prefix gets propagated through this call into F2XOs?! - // Dc dc = (Dc) item.getNestedNameSpace("dc"); - // if (dc != null) - // { - // dc.serialize(System.err); - // System.err.println('\n'); - // } - } - } - println("\n"); - - SimplTypesScope.serialize(rdfState, System.err, StringFormat.XML); - - println("\n"); - SimplTypesScope.serialize(rdfState, System.err, StringFormat.XML); - - // RssState rssState2 = (RssState) ElementState.translateFromXMLCharSequence(retranslated, - // RssTranslations.get()); - // rssState2.translateToXML(System.out); - - // rssState.translateToXML(outputFile); - - println("\n"); - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - -} +package ecologylab.serialization.library.rss; + +import java.io.File; +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * Alternative root element {@link ecologylab.serialization.ElementState ElementState} declarations + * for RSS parser: that nasty RSS versions: .90 and 1.0. + *

+ * This is a bit of a hack, in that it makes no attempt to handle general RDF, or to support + * namespace definitions with great depth. + *

+ * Those things can be done with this framework. One of these days, an application will drive + * someone to develop such extensions. + * + * @author andruid + */ +// @xml_inherit +@simpl_tag("rdf:RDF") +public class RDFState extends ElementState // ArrayListState +{ + @simpl_nowrap + @simpl_collection("item") + ArrayList items; + + public RDFState() + { + super(); + } + + public int size() + { + return (items == null) ? 0 : items.size(); + } + + /** + * Get Item elements associated with a feed. + * + * @param i + * Index of the item in this collection. + * @return The ith Item object directly collected in this, or null if there are no Items. + */ + public Item get(int i) + { + return items == null ? null : items.get(i); + } + + // protected Collection getCollection(Class thatClass) + // { + // return Item.class.equals(thatClass) ? + // super.getCollection(thatClass) : null; + // } + + static final String DELICIOUS_EXAMPLE = "\r\n" + + "\r\n" + + "\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "Java Pro Online - Output Namespace-Aware XML Documents\r\n" + + "http://209.85.165.104/search?q=cache:hQMa26l1za0J:www.ftponline.com/javapro/2003_06/online/namespace_kjones_06_23_03/+namespace+declaration+java+xml&hl=en&ct=clnk&cd=4&gl=us&client=firefox-a\r\n" + + "\r\n" + + ".createElementNS\r\n" + + "andruid\r\n" + + "2007-11-19T05:56:11Z\r\n" + + "ecologylab java namespace xml\r\n" + + "\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + "\r\n" + + "\r\n" + "\r\n" + ""; + + static final ParsedURL DELICIOUS_POPULAR = ParsedURL + .getAbsolute("http://del.icio.us/rss/popular/"); + + public static final ParsedURL DELICIOUS_FEED = ParsedURL + .getAbsolute("http://del.icio.us/rss/andruid/"); + + public static final File outputFile = new File("/temp/rss.xml"); + + public static void main(String[] args) + { + // ElementState.setUseDOMForTranslateTo(true); + try + { + // ParsedURL feedPURL = CNN_TOP_FEED; + ParsedURL feedPURL = DELICIOUS_FEED; // DELICIOUS_POPULAR; + println("Translating RSS feed: " + feedPURL + "\n"); + + RDFState rdfState = (RDFState) RssTranslations.get().deserialize(feedPURL, Format.XML); + // RDFState rdfState = (RDFState) ElementState.translateFromXMLCharSequence(DELICIOUS_EXAMPLE, + // RssTranslations.get()); + + ArrayList items = rdfState.items; // rssState.getChannel().getItems(); + println("items: " + rdfState.size()); + if (items != null) + { + for (Item item : items) + { + println("description:\t" + item.description); + // FIXME! -- how do we make sure the prefix gets propagated through this call into F2XOs?! + // Dc dc = (Dc) item.getNestedNameSpace("dc"); + // if (dc != null) + // { + // dc.serialize(System.err); + // System.err.println('\n'); + // } + } + } + println("\n"); + + SimplTypesScope.serialize(rdfState, System.err, StringFormat.XML); + + println("\n"); + SimplTypesScope.serialize(rdfState, System.err, StringFormat.XML); + + // RssState rssState2 = (RssState) ElementState.translateFromXMLCharSequence(retranslated, + // RssTranslations.get()); + // rssState2.translateToXML(System.out); + + // rssState.translateToXML(outputFile); + + println("\n"); + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/rss/RssState.java b/simplCore/src/ecologylab/serialization/library/rss/RssState.java index 98296858..e94bb66c 100644 --- a/simplCore/src/ecologylab/serialization/library/rss/RssState.java +++ b/simplCore/src/ecologylab/serialization/library/rss/RssState.java @@ -1,298 +1,298 @@ -package ecologylab.serialization.library.rss; - -import java.io.File; -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * {@link ecologylab.serialization.ElementState ElementState} for the root element of the RSS - * parser. In particular, this supports RSS versions such as .91, .92, .93, .94, and 2.0. - * - * @author andruid - */ -public class RssState extends ElementState -{ - @simpl_scalar - float version; - - @simpl_composite - Channel channel; - - /** - * @return Returns the channel. - */ - public Channel getChannel() - { - return channel; - } - - /** - * @param channel - * The channel to set. - */ - public void setChannel(Channel channel) - { - this.channel = channel; - } - - /** - * @return Returns the version. - */ - public float getVersion() - { - return version; - } - - /** - * @param version - * The version to set. - */ - public void setVersion(float version) - { - this.version = version; - } - - public static final ParsedURL NYT_TECH_FEED = ParsedURL - .getAbsolute("http://www.nytimes.com/services/xml/rss/nyt/Technology.xml"); - - public static final ParsedURL CNN_TOP_FEED = ParsedURL - .getAbsolute("http://rss.cnn.com/rss/cnn_topstories.rss"); - - public static final ParsedURL BBC_FRONT_FEED = ParsedURL - .getAbsolute("http://news.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml"); - - public static final ParsedURL ABC_SPORTS_FEED = ParsedURL - .getAbsolute("http://my.abcnews.go.com/rsspublic/sports_rss20.xml"); - - public static final ParsedURL FLICKR_FEED = ParsedURL - .getAbsolute("http://www.flickr.com/services/feeds/photos_public.gne?format=rss_200&tags=sunset"); - - public static final ParsedURL DELICIOUS_FEED = ParsedURL - .getAbsolute("http://del.icio.us/rss/andruid/"); - - public static final String ABC_EXAMPLE = "\r\n" - + " \r\n" - + "\r\n" - + "\r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + "\r\n" - + " Pats Steamroll Bills, Move to 10-0\r\n" - + " http://feeds.feedburner.com/~r/AbcNews_Sports/~3/186994604/wireStory\r\n" - + " \r\n" - + " Lead by Tom Brady and Randy Moss, Pats scored TDs on their first 7 possessions.<img src=\"http://feeds.feedburner.com/~r/AbcNews_Sports/~4/186994604\" height=\"1\" width=\"1\"/> \r\n" - + "" - + "\r\n" - + "\r\n" - + "\r\n"; - - public static final String NS_EXAMPLE = "\r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + " Musharraf \'will quit army soon\' \r\n" - + " Pakistan\'s attorney general says he expects President Musharraf to resign as army head before 1 December. \r\n" - + " http://news.bbc.co.uk/go/rss/-/2/hi/south_asia/7096381.stm \r\n" - + " http://news.bbc.co.uk/2/hi/south_asia/7096381.stm \r\n" - + " Thu, 15 Nov 2007 13:58:24 GMT \r\n" - + " South Asia \r\n" - + " \r\n" - + " \r\n" - + " Canadian stun gun death on video \r\n" - + " A video is released of a Polish immigrant\'s death after he was stun gunned by police at Vancouver airport. \r\n" - + " http://news.bbc.co.uk/go/rss/-/2/hi/americas/7095875.stm \r\n" - + " http://news.bbc.co.uk/2/hi/americas/7095875.stm \r\n" - + " Thu, 15 Nov 2007 11:18:54 GMT \r\n" - + " Americas \r\n" - + " \r\n" - + " \r\n" - + " \r\n" - + ""; - - public static final String FEEDBURNER_EXAMPlE = "\r\n" - + "\r\n" - + "CNN.com\r\n" - + "\r\n" - + "\r\n" - + "http://www.cnn.com/2007/POLITICS/11/16/congress.crandallmine/index.html\r\n" - + "Utah mine owner faces Senate panel subpoena\r\n" - + "\r\n" - + "http://www.cnn.com/2007/POLITICS/11/16/congress.crandallmine/index.html\r\n" - + "http://rss.cnn.com/~r/rss/cnn_topstories/~3/186060716/index.html\r\n" - + "A Senate subcommittee probing this summer\'s deadly Utah mine disaster has subpoenaed the mine\'s co-owner, ranking member Sen. Arlen Specter said Friday.\r\n" - + "Fri, 16 Nov 2007 19:53:04 EST\r\n" - + "\r\n" - + "\r\n" - + "\r\n" - + "\r\n"; - - public static final String FLICKR_EXAMPLE = "\r\n" - + " \r\n" - + " Photos from everyone tagged water\r\n" - + " http://www.flickr.com/photos/tags/water/\r\n" - + " \r\n" - + " Fire-Worksing\r\n" - + " Fire-Works\r\n" - + " http://www.flickr.com/photos/meemz/2161548299/\r\n" - + " Fire-Works\r\n" - + "\r\n" + " \r\n" - + "\r\n" + "\r\n"; - - public static final String ITEM_EXAMPLE = " \r\n" - + " Fire-Works\r\n" - + " \r\n" - + " Fire-Works\r\n" - + " http://www.flickr.com/photos/meemz/2161548299/\r\n" - + - // " Fire-Works\r\n" - // + - "\r\n" - + " \r\n" - + " Photos from everyone tagged water\r\n" - + " http://www.flickr.com/photos/tags/water/\r\n" - + "\r\n"; - - public static final String NABEEL_TEST = "" - + "" - + " title.Nabeel" - + " description.Student" - + " http://www.google.com/ig" - + " " - + " " - + " Item.title.Nabeel" - + " Item.description.Nabeel" - + " http://www.google.com/ig" - + " http://www.google.com/ig" - + " Item.author.Nabeel" - + " newCat 0" - + " newCat 1" - + " " - + " " - + " Item.title.Nabeel" - + " Item.description.Nabeel" - + " http://www.google.com/ig" - + " http://www.google.com/ig" - + " Item.author.Nabeel" - + " newCat 0" - + " newCat 1" - + " " + " " + "" - + ""; - - public static final File outputFile = new File("/temp/rss.xml"); - - public static void main(String[] args) - { - ElementState rss; - try - { - // rss = translateFromXMLCharSequence(FLICKR_EXAMPLE, RssTranslations.get()); - // rss = translateFromXMLCharSequence(NABEEL_TEST, RssTranslations.get()); - rss = (ElementState) RssTranslations.get().deserialize(CNN_TOP_FEED, Format.XML); - - System.out.println(""); - SimplTypesScope.serialize(rss, System.out, StringFormat.XML); - - System.out.println(""); - - // RssTranslations.get().translateToXML(System.out); - - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private static void mostMinimalTranlateToTest() - { - ClassDescriptor fdClassDescriptor = ClassDescriptor.getClassDescriptor(FieldDescriptor.class); - RssState rss = new RssState(); - Channel channel = new Channel(); - rss.channel = channel; - - try - { - - SimplTypesScope.serialize(rss, System.out, StringFormat.XML); - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private static void doMain() - { - try - { - // ParsedURL feedPURL = ABC_SPORTS_FEED; // CNN_TOP_FEED; - ParsedURL feedPURL = DELICIOUS_FEED; // FLICKR_FEED; - println("Translating RSS feed: " + feedPURL + "\n"); - - RssState rssState = (RssState) RssTranslations.get().deserialize(feedPURL, Format.XML); - // RssState rssState = (RssState) ElementState.translateFromXMLCharSequence(FLICKR_EXAMPLE, - // RssTranslations.get()); - - ArrayList items = rssState.getChannel().items; // rssState.getChannel().getItems(); - println("items: " + items.size()); - for (Item item : items) - { - println("description:\t" + item.description); - // FIXME! -- how do we make sure the prefix gets propagated through this call into F2XOs?! - // Media media = (Media) item.getNestedNameSpace("media"); - // if (media != null) - // { - // Thumbnail thumbnail = media.getThumbnail(); - // if (thumbnail != null) - // thumbnail.serialize(System.err); - // // media.translateToXML(System.err); - // System.err.println('\n'); - // } - // Feedburner feedburner = (Feedburner) item.getNestedNameSpace("feedburner"); - // if (feedburner != null) - // { - // ClassDescriptor.serialize(feedburner, System.err, StringFormat.XML); - // feedburner.serialize(System.err); - // System.err.println('\n'); - // } - } - - SimplTypesScope.serialize(rssState, System.err, StringFormat.XML); - - println("\n"); - SimplTypesScope.serialize(rssState, System.err, StringFormat.XML); - - println("\n"); - - // RssState rssState2 = (RssState) ElementState.translateFromXMLCharSequence(retranslated, - // RssTranslations.get()); - // rssState2.translateToXML(System.out); - - // rssState.translateToXML(outputFile); - - println("\n"); - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } -} +package ecologylab.serialization.library.rss; + +import java.io.File; +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * {@link ecologylab.serialization.ElementState ElementState} for the root element of the RSS + * parser. In particular, this supports RSS versions such as .91, .92, .93, .94, and 2.0. + * + * @author andruid + */ +public class RssState extends ElementState +{ + @simpl_scalar + float version; + + @simpl_composite + Channel channel; + + /** + * @return Returns the channel. + */ + public Channel getChannel() + { + return channel; + } + + /** + * @param channel + * The channel to set. + */ + public void setChannel(Channel channel) + { + this.channel = channel; + } + + /** + * @return Returns the version. + */ + public float getVersion() + { + return version; + } + + /** + * @param version + * The version to set. + */ + public void setVersion(float version) + { + this.version = version; + } + + public static final ParsedURL NYT_TECH_FEED = ParsedURL + .getAbsolute("http://www.nytimes.com/services/xml/rss/nyt/Technology.xml"); + + public static final ParsedURL CNN_TOP_FEED = ParsedURL + .getAbsolute("http://rss.cnn.com/rss/cnn_topstories.rss"); + + public static final ParsedURL BBC_FRONT_FEED = ParsedURL + .getAbsolute("http://news.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml"); + + public static final ParsedURL ABC_SPORTS_FEED = ParsedURL + .getAbsolute("http://my.abcnews.go.com/rsspublic/sports_rss20.xml"); + + public static final ParsedURL FLICKR_FEED = ParsedURL + .getAbsolute("http://www.flickr.com/services/feeds/photos_public.gne?format=rss_200&tags=sunset"); + + public static final ParsedURL DELICIOUS_FEED = ParsedURL + .getAbsolute("http://del.icio.us/rss/andruid/"); + + public static final String ABC_EXAMPLE = "\r\n" + + " \r\n" + + "\r\n" + + "\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + "\r\n" + + " Pats Steamroll Bills, Move to 10-0\r\n" + + " http://feeds.feedburner.com/~r/AbcNews_Sports/~3/186994604/wireStory\r\n" + + " \r\n" + + " Lead by Tom Brady and Randy Moss, Pats scored TDs on their first 7 possessions.<img src=\"http://feeds.feedburner.com/~r/AbcNews_Sports/~4/186994604\" height=\"1\" width=\"1\"/> \r\n" + + "" + + "\r\n" + + "\r\n" + + "\r\n"; + + public static final String NS_EXAMPLE = "\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " Musharraf \'will quit army soon\' \r\n" + + " Pakistan\'s attorney general says he expects President Musharraf to resign as army head before 1 December. \r\n" + + " http://news.bbc.co.uk/go/rss/-/2/hi/south_asia/7096381.stm \r\n" + + " http://news.bbc.co.uk/2/hi/south_asia/7096381.stm \r\n" + + " Thu, 15 Nov 2007 13:58:24 GMT \r\n" + + " South Asia \r\n" + + " \r\n" + + " \r\n" + + " Canadian stun gun death on video \r\n" + + " A video is released of a Polish immigrant\'s death after he was stun gunned by police at Vancouver airport. \r\n" + + " http://news.bbc.co.uk/go/rss/-/2/hi/americas/7095875.stm \r\n" + + " http://news.bbc.co.uk/2/hi/americas/7095875.stm \r\n" + + " Thu, 15 Nov 2007 11:18:54 GMT \r\n" + + " Americas \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + ""; + + public static final String FEEDBURNER_EXAMPlE = "\r\n" + + "\r\n" + + "CNN.com\r\n" + + "\r\n" + + "\r\n" + + "http://www.cnn.com/2007/POLITICS/11/16/congress.crandallmine/index.html\r\n" + + "Utah mine owner faces Senate panel subpoena\r\n" + + "\r\n" + + "http://www.cnn.com/2007/POLITICS/11/16/congress.crandallmine/index.html\r\n" + + "http://rss.cnn.com/~r/rss/cnn_topstories/~3/186060716/index.html\r\n" + + "A Senate subcommittee probing this summer\'s deadly Utah mine disaster has subpoenaed the mine\'s co-owner, ranking member Sen. Arlen Specter said Friday.\r\n" + + "Fri, 16 Nov 2007 19:53:04 EST\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n"; + + public static final String FLICKR_EXAMPLE = "\r\n" + + " \r\n" + + " Photos from everyone tagged water\r\n" + + " http://www.flickr.com/photos/tags/water/\r\n" + + " \r\n" + + " Fire-Worksing\r\n" + + " Fire-Works\r\n" + + " http://www.flickr.com/photos/meemz/2161548299/\r\n" + + " Fire-Works\r\n" + + "\r\n" + " \r\n" + + "\r\n" + "\r\n"; + + public static final String ITEM_EXAMPLE = " \r\n" + + " Fire-Works\r\n" + + " \r\n" + + " Fire-Works\r\n" + + " http://www.flickr.com/photos/meemz/2161548299/\r\n" + + + // " Fire-Works\r\n" + // + + "\r\n" + + " \r\n" + + " Photos from everyone tagged water\r\n" + + " http://www.flickr.com/photos/tags/water/\r\n" + + "\r\n"; + + public static final String NABEEL_TEST = "" + + "" + + " title.Nabeel" + + " description.Student" + + " http://www.google.com/ig" + + " " + + " " + + " Item.title.Nabeel" + + " Item.description.Nabeel" + + " http://www.google.com/ig" + + " http://www.google.com/ig" + + " Item.author.Nabeel" + + " newCat 0" + + " newCat 1" + + " " + + " " + + " Item.title.Nabeel" + + " Item.description.Nabeel" + + " http://www.google.com/ig" + + " http://www.google.com/ig" + + " Item.author.Nabeel" + + " newCat 0" + + " newCat 1" + + " " + " " + "" + + ""; + + public static final File outputFile = new File("/temp/rss.xml"); + + public static void main(String[] args) + { + ElementState rss; + try + { + // rss = translateFromXMLCharSequence(FLICKR_EXAMPLE, RssTranslations.get()); + // rss = translateFromXMLCharSequence(NABEEL_TEST, RssTranslations.get()); + rss = (ElementState) RssTranslations.get().deserialize(CNN_TOP_FEED, Format.XML); + + System.out.println(""); + SimplTypesScope.serialize(rss, System.out, StringFormat.XML); + + System.out.println(""); + + // RssTranslations.get().translateToXML(System.out); + + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private static void mostMinimalTranlateToTest() + { + ClassDescriptor fdClassDescriptor = ClassDescriptor.getClassDescriptor(FieldDescriptor.class); + RssState rss = new RssState(); + Channel channel = new Channel(); + rss.channel = channel; + + try + { + + SimplTypesScope.serialize(rss, System.out, StringFormat.XML); + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private static void doMain() + { + try + { + // ParsedURL feedPURL = ABC_SPORTS_FEED; // CNN_TOP_FEED; + ParsedURL feedPURL = DELICIOUS_FEED; // FLICKR_FEED; + println("Translating RSS feed: " + feedPURL + "\n"); + + RssState rssState = (RssState) RssTranslations.get().deserialize(feedPURL, Format.XML); + // RssState rssState = (RssState) ElementState.translateFromXMLCharSequence(FLICKR_EXAMPLE, + // RssTranslations.get()); + + ArrayList items = rssState.getChannel().items; // rssState.getChannel().getItems(); + println("items: " + items.size()); + for (Item item : items) + { + println("description:\t" + item.description); + // FIXME! -- how do we make sure the prefix gets propagated through this call into F2XOs?! + // Media media = (Media) item.getNestedNameSpace("media"); + // if (media != null) + // { + // Thumbnail thumbnail = media.getThumbnail(); + // if (thumbnail != null) + // thumbnail.serialize(System.err); + // // media.translateToXML(System.err); + // System.err.println('\n'); + // } + // Feedburner feedburner = (Feedburner) item.getNestedNameSpace("feedburner"); + // if (feedburner != null) + // { + // ClassDescriptor.serialize(feedburner, System.err, StringFormat.XML); + // feedburner.serialize(System.err); + // System.err.println('\n'); + // } + } + + SimplTypesScope.serialize(rssState, System.err, StringFormat.XML); + + println("\n"); + SimplTypesScope.serialize(rssState, System.err, StringFormat.XML); + + println("\n"); + + // RssState rssState2 = (RssState) ElementState.translateFromXMLCharSequence(retranslated, + // RssTranslations.get()); + // rssState2.translateToXML(System.out); + + // rssState.translateToXML(outputFile); + + println("\n"); + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/simplCore/src/ecologylab/serialization/library/rss/RssTranslationScopt.xml b/simplCore/src/ecologylab/serialization/library/rss/RssTranslationScopt.xml index 72748563..04d200a7 100644 --- a/simplCore/src/ecologylab/serialization/library/rss/RssTranslationScopt.xml +++ b/simplCore/src/ecologylab/serialization/library/rss/RssTranslationScopt.xml @@ -1,37 +1,37 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/library/rss/RssTranslations.java b/simplCore/src/ecologylab/serialization/library/rss/RssTranslations.java index 2bb7f547..93afd6e3 100644 --- a/simplCore/src/ecologylab/serialization/library/rss/RssTranslations.java +++ b/simplCore/src/ecologylab/serialization/library/rss/RssTranslations.java @@ -1,87 +1,87 @@ -package ecologylab.serialization.library.rss; - -import ecologylab.generic.Debug; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * Translations for all RSS parsing. - * - * @author andruid - */ -public class RssTranslations extends Debug -{ - private static final String TRANSLATION_SPACE_NAME = "rss"; - - public static final Class TRANSLATIONS[] = - { RssState.class, Channel.class, Item.class, - - // Dc.class, - // - // - // RDFState.class, - }; - - /* - * public static final TranslationScope INHERITED_TRANSLATIONS[] = { Media.getTranslations(), - * - * }; - * - * public static final NameSpaceDecl[] NAME_SPACE_DECLS = { new - * NameSpaceDecl("http://search.yahoo.com/mrss/", Media.class, Media.getTranslations()), new - * NameSpaceDecl("http://rssnamespace.org/feedburner/ext/1.0", Feedburner.class, - * Feedburner.get()), new NameSpaceDecl("http://purl.org/dc/elements/1.1/", Dc.class, Dc.get()), - * - * }; - */ - /** - * Just prevent anyone from new'ing this. - */ - private RssTranslations() - { - } - - public static SimplTypesScope get() - { - return SimplTypesScope.get(TRANSLATION_SPACE_NAME, /* NAME_SPACE_DECLS,INHERITED_TRANSLATIONS, */ - TRANSLATIONS); - } - - public static final String OUT = ""; - - static final ParsedURL FLICKR_PURL = ParsedURL - .getAbsolute( - "http://www.flickr.com/services/feeds/photos_public.gne?format=rss_200&tags=freedom", - ""); - - public static void main(String[] args) - { - SimplTypesScope tScope = get(); - - try - { - StringBuilder buffy = new StringBuilder(); - SimplTypesScope.serialize(tScope, System.out, StringFormat.XML); - - System.out.println('\n'); - - ElementState translated = (ElementState) SimplTypesScope.getBasicTranslations().deserialize( - buffy, StringFormat.XML); - // ElementState.translateFromXMLCharSequence(OUT, TranslationScope.getBasicTranslations()); - - SimplTypesScope.serialize(translated, System.out, StringFormat.XML); - - System.out.println('\n'); - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - System.out.println("\n"); - } - -} +package ecologylab.serialization.library.rss; + +import ecologylab.generic.Debug; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * Translations for all RSS parsing. + * + * @author andruid + */ +public class RssTranslations extends Debug +{ + private static final String TRANSLATION_SPACE_NAME = "rss"; + + public static final Class TRANSLATIONS[] = + { RssState.class, Channel.class, Item.class, + + // Dc.class, + // + // + // RDFState.class, + }; + + /* + * public static final TranslationScope INHERITED_TRANSLATIONS[] = { Media.getTranslations(), + * + * }; + * + * public static final NameSpaceDecl[] NAME_SPACE_DECLS = { new + * NameSpaceDecl("http://search.yahoo.com/mrss/", Media.class, Media.getTranslations()), new + * NameSpaceDecl("http://rssnamespace.org/feedburner/ext/1.0", Feedburner.class, + * Feedburner.get()), new NameSpaceDecl("http://purl.org/dc/elements/1.1/", Dc.class, Dc.get()), + * + * }; + */ + /** + * Just prevent anyone from new'ing this. + */ + private RssTranslations() + { + } + + public static SimplTypesScope get() + { + return SimplTypesScope.get(TRANSLATION_SPACE_NAME, /* NAME_SPACE_DECLS,INHERITED_TRANSLATIONS, */ + TRANSLATIONS); + } + + public static final String OUT = ""; + + static final ParsedURL FLICKR_PURL = ParsedURL + .getAbsolute( + "http://www.flickr.com/services/feeds/photos_public.gne?format=rss_200&tags=freedom", + ""); + + public static void main(String[] args) + { + SimplTypesScope tScope = get(); + + try + { + StringBuilder buffy = new StringBuilder(); + SimplTypesScope.serialize(tScope, System.out, StringFormat.XML); + + System.out.println('\n'); + + ElementState translated = (ElementState) SimplTypesScope.getBasicTranslations().deserialize( + buffy, StringFormat.XML); + // ElementState.translateFromXMLCharSequence(OUT, TranslationScope.getBasicTranslations()); + + SimplTypesScope.serialize(translated, System.out, StringFormat.XML); + + System.out.println('\n'); + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + System.out.println("\n"); + } + +} diff --git a/simplCore/src/ecologylab/serialization/library/rss/package.html b/simplCore/src/ecologylab/serialization/library/rss/package.html index e7843664..9eb606f7 100644 --- a/simplCore/src/ecologylab/serialization/library/rss/package.html +++ b/simplCore/src/ecologylab/serialization/library/rss/package.html @@ -1,5 +1,5 @@ - -Ecologylab.XML derived classes of ElementState that -implement an RSS parser. - + +Ecologylab.XML derived classes of ElementState that +implement an RSS parser. + \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/library/rss/test.xml b/simplCore/src/ecologylab/serialization/library/rss/test.xml index bc9dc00a..8fb32286 100644 --- a/simplCore/src/ecologylab/serialization/library/rss/test.xml +++ b/simplCore/src/ecologylab/serialization/library/rss/test.xml @@ -1,28 +1,28 @@ - - - title.Nabeel - description.Student - http://www.google.com/ig - - - Item.title.Nabeel - Item.description.Nabeel - http://www.google.com/ig - http://www.google.com/ig - Item.author.Nabeel - newCat 0 - newCat 1 - - - Item.title.Nabeel - Item.description.Nabeel - http://www.google.com/ig - http://www.google.com/ig - Item.author.Nabeel - newCat 0 - newCat 1 - - - - - + + + title.Nabeel + description.Student + http://www.google.com/ig + + + Item.title.Nabeel + Item.description.Nabeel + http://www.google.com/ig + http://www.google.com/ig + Item.author.Nabeel + newCat 0 + newCat 1 + + + Item.title.Nabeel + Item.description.Nabeel + http://www.google.com/ig + http://www.google.com/ig + Item.author.Nabeel + newCat 0 + newCat 1 + + + + + diff --git a/simplCore/src/ecologylab/serialization/library/yahoo/Result.java b/simplCore/src/ecologylab/serialization/library/yahoo/Result.java index 498f42a1..7fa21bda 100644 --- a/simplCore/src/ecologylab/serialization/library/yahoo/Result.java +++ b/simplCore/src/ecologylab/serialization/library/yahoo/Result.java @@ -1,188 +1,188 @@ -package ecologylab.serialization.library.yahoo; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * Result from a Yahoo Search. - * - * This implementation has fields for "web search" and "image search". - * I expect other fields will get added for other types of search. - * - * @author andruid - */ -public -@simpl_tag("Result") -class Result extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Title") String title; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Summary") String summary; - /** - * For web search, the URL of the document. - * For image search, the URL of the image. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Url") ParsedURL url; - - // this is a mess double-stuffed url from yahoo. nice to ignore. -// @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("ClickUrl") ParsedURL clickUrl; - - // there is also a field called ClickUrl. for image search, it duplicates Url. - // for web search ClickUrl is that nasty url that takes you through yahoo, and includes - // a url-encoded : after http, in the middle - /** - * For image search, this is the Container web page! - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("RefererUrl") ParsedURL refererUrl; - - /** - * Another field for image search only. How useful! - * Lets us know if we want to work with the thumbnail or just download the whole image. - * Seems to be in bytes. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("FileSize") int fileSize; - - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Width") int width; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Height") int height; - - /** - * For image search only. This seems to be the file suffix, though they use jpeg instead of jpg. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("FileFormat") String fileFormat; - - /** - * Specific to news search. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("NewsSource") String newsSource; - - /** - * For web search only. Like file format, except its true mime type, like text/html. - * Very nice. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("MimeType") String mimeType; - - // DisplayUrl -- boring. Web search only. - - // Modification Date -- again, we need a Date type!!! looks like they are providing the long int format - // For web search and image search. - - /** - * Cool! For image search, direct access to their thumbnail image. - */ - @simpl_composite @simpl_tag("Thumbnail") ThumbnailState thumbnail; - - - public String getTitle() - { - return title; - } - - public void setTitle(String title) - { - this.title = title; - } - - public String getSummary() - { - return summary; - } - - public void setSummary(String summary) - { - this.summary = summary; - } - - public ParsedURL getUrl() - { - return url; - } - - public void setUrl(ParsedURL url) - { - this.url = url; - } - - public ParsedURL getRefererUrl() - { - return refererUrl; - } - - public void setRefererUrl(ParsedURL refererUrl) - { - this.refererUrl = refererUrl; - } - - public int getFileSize() - { - return fileSize; - } - - public void setFileSize(int fileSize) - { - this.fileSize = fileSize; - } - - public int getWidth() - { - return width; - } - - public void setWidth(int width) - { - this.width = width; - } - - public int getHeight() - { - return height; - } - - public void setHeight(int height) - { - this.height = height; - } - - public String getFileFormat() - { - return fileFormat; - } - - public void setFileFormat(String fileFormat) - { - this.fileFormat = fileFormat; - } - - public String getNewsSource() - { - return newsSource; - } - - public void setNewsSource(String newsSource) - { - this.newsSource = newsSource; - } - - public String getMimeType() - { - return mimeType; - } - - public void setMimeType(String mimeType) - { - this.mimeType = mimeType; - } - - public ThumbnailState getThumbnail() - { - return this.thumbnail; - } - - public void setThumbnail(ThumbnailState thumbnail) - { - this.thumbnail = thumbnail; - } -} +package ecologylab.serialization.library.yahoo; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * Result from a Yahoo Search. + * + * This implementation has fields for "web search" and "image search". + * I expect other fields will get added for other types of search. + * + * @author andruid + */ +public +@simpl_tag("Result") +class Result extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Title") String title; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Summary") String summary; + /** + * For web search, the URL of the document. + * For image search, the URL of the image. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Url") ParsedURL url; + + // this is a mess double-stuffed url from yahoo. nice to ignore. +// @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("ClickUrl") ParsedURL clickUrl; + + // there is also a field called ClickUrl. for image search, it duplicates Url. + // for web search ClickUrl is that nasty url that takes you through yahoo, and includes + // a url-encoded : after http, in the middle + /** + * For image search, this is the Container web page! + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("RefererUrl") ParsedURL refererUrl; + + /** + * Another field for image search only. How useful! + * Lets us know if we want to work with the thumbnail or just download the whole image. + * Seems to be in bytes. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("FileSize") int fileSize; + + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Width") int width; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Height") int height; + + /** + * For image search only. This seems to be the file suffix, though they use jpeg instead of jpg. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("FileFormat") String fileFormat; + + /** + * Specific to news search. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("NewsSource") String newsSource; + + /** + * For web search only. Like file format, except its true mime type, like text/html. + * Very nice. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("MimeType") String mimeType; + + // DisplayUrl -- boring. Web search only. + + // Modification Date -- again, we need a Date type!!! looks like they are providing the long int format + // For web search and image search. + + /** + * Cool! For image search, direct access to their thumbnail image. + */ + @simpl_composite @simpl_tag("Thumbnail") ThumbnailState thumbnail; + + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getSummary() + { + return summary; + } + + public void setSummary(String summary) + { + this.summary = summary; + } + + public ParsedURL getUrl() + { + return url; + } + + public void setUrl(ParsedURL url) + { + this.url = url; + } + + public ParsedURL getRefererUrl() + { + return refererUrl; + } + + public void setRefererUrl(ParsedURL refererUrl) + { + this.refererUrl = refererUrl; + } + + public int getFileSize() + { + return fileSize; + } + + public void setFileSize(int fileSize) + { + this.fileSize = fileSize; + } + + public int getWidth() + { + return width; + } + + public void setWidth(int width) + { + this.width = width; + } + + public int getHeight() + { + return height; + } + + public void setHeight(int height) + { + this.height = height; + } + + public String getFileFormat() + { + return fileFormat; + } + + public void setFileFormat(String fileFormat) + { + this.fileFormat = fileFormat; + } + + public String getNewsSource() + { + return newsSource; + } + + public void setNewsSource(String newsSource) + { + this.newsSource = newsSource; + } + + public String getMimeType() + { + return mimeType; + } + + public void setMimeType(String mimeType) + { + this.mimeType = mimeType; + } + + public ThumbnailState getThumbnail() + { + return this.thumbnail; + } + + public void setThumbnail(ThumbnailState thumbnail) + { + this.thumbnail = thumbnail; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/yahoo/ResultSet.java b/simplCore/src/ecologylab/serialization/library/yahoo/ResultSet.java index 450fe660..5ccacf57 100644 --- a/simplCore/src/ecologylab/serialization/library/yahoo/ResultSet.java +++ b/simplCore/src/ecologylab/serialization/library/yahoo/ResultSet.java @@ -1,95 +1,95 @@ -package ecologylab.serialization.library.yahoo; - -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * Top level result set collection element for Yahoo search. The collected elements are all of type - * result. - * - * http://www.yahooapis.com/search/web/V1/webSearch.html - * - * @author andruid - */ -@simpl_inherit -@simpl_tag("ResultSet") -public class ResultSet extends ElementState -{ - - @simpl_scalar - @simpl_tag("xsi:schemaLocation") - String schemaLocation; - - @simpl_scalar - @simpl_tag("type") - String type; - - @simpl_scalar - @simpl_tag("moreSearch") - String moreSearch; - - @simpl_scalar - @simpl_tag("totalResultsAvailable") - int totalResultsAvailable; - - @simpl_scalar - @simpl_tag("totalResultsReturned") - int totalResultsReturned; - - @simpl_scalar - @simpl_tag("firstResultPosition") - int firstResultPosition; - - @simpl_nowrap - @simpl_collection("Result") - ArrayList results; - - public static final String YAHOO = "yahoo"; - - public static final Class[] YAHOO_CLASSES = - { ResultSet.class, Result.class, ThumbnailState.class, }; - - public static SimplTypesScope getTranslationScope() - { - return SimplTypesScope.get(YAHOO, YAHOO_CLASSES); - } - - public static String SEOUL_SHOPPING = "http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=yahoosearchwebrss&results=15&start=1&query=shopping+seoul"; - - public static void main(String[] a) - { - ParsedURL purl = ParsedURL.getAbsolute(SEOUL_SHOPPING, "uck"); - try - { - ResultSet resultSet = (ResultSet) ResultSet.getTranslationScope().deserialize(purl, - Format.XML); - - SimplTypesScope.serialize(resultSet, System.out, StringFormat.XML); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - } - - public Result get(int i) - { - return results == null ? null : results.get(i); - } - - public int size() - { - return results == null ? 0 : results.size(); - } -} +package ecologylab.serialization.library.yahoo; + +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * Top level result set collection element for Yahoo search. The collected elements are all of type + * result. + * + * http://www.yahooapis.com/search/web/V1/webSearch.html + * + * @author andruid + */ +@simpl_inherit +@simpl_tag("ResultSet") +public class ResultSet extends ElementState +{ + + @simpl_scalar + @simpl_tag("xsi:schemaLocation") + String schemaLocation; + + @simpl_scalar + @simpl_tag("type") + String type; + + @simpl_scalar + @simpl_tag("moreSearch") + String moreSearch; + + @simpl_scalar + @simpl_tag("totalResultsAvailable") + int totalResultsAvailable; + + @simpl_scalar + @simpl_tag("totalResultsReturned") + int totalResultsReturned; + + @simpl_scalar + @simpl_tag("firstResultPosition") + int firstResultPosition; + + @simpl_nowrap + @simpl_collection("Result") + ArrayList results; + + public static final String YAHOO = "yahoo"; + + public static final Class[] YAHOO_CLASSES = + { ResultSet.class, Result.class, ThumbnailState.class, }; + + public static SimplTypesScope getTranslationScope() + { + return SimplTypesScope.get(YAHOO, YAHOO_CLASSES); + } + + public static String SEOUL_SHOPPING = "http://api.search.yahoo.com/WebSearchService/V1/webSearch?appid=yahoosearchwebrss&results=15&start=1&query=shopping+seoul"; + + public static void main(String[] a) + { + ParsedURL purl = ParsedURL.getAbsolute(SEOUL_SHOPPING, "uck"); + try + { + ResultSet resultSet = (ResultSet) ResultSet.getTranslationScope().deserialize(purl, + Format.XML); + + SimplTypesScope.serialize(resultSet, System.out, StringFormat.XML); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + } + + public Result get(int i) + { + return results == null ? null : results.get(i); + } + + public int size() + { + return results == null ? 0 : results.size(); + } +} diff --git a/simplCore/src/ecologylab/serialization/library/yahoo/ThumbnailState.java b/simplCore/src/ecologylab/serialization/library/yahoo/ThumbnailState.java index e771ddfa..f5bf2ebe 100644 --- a/simplCore/src/ecologylab/serialization/library/yahoo/ThumbnailState.java +++ b/simplCore/src/ecologylab/serialization/library/yahoo/ThumbnailState.java @@ -1,53 +1,53 @@ -package ecologylab.serialization.library.yahoo; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * Yahoo image search Thumbnail image XML description. - * - * @author andruid - */ -public -@simpl_tag("Thumbnail") -class ThumbnailState extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Url") ParsedURL url; - - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Width") int width; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Height") int height; - - public ParsedURL getUrl() - { - return url; - } - - public void setUrl(ParsedURL url) - { - this.url = url; - } - - public int getWidth() - { - return width; - } - - public void setWidth(int width) - { - this.width = width; - } - - public int getHeight() - { - return height; - } - - public void setHeight(int height) - { - this.height = height; - } -} +package ecologylab.serialization.library.yahoo; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * Yahoo image search Thumbnail image XML description. + * + * @author andruid + */ +public +@simpl_tag("Thumbnail") +class ThumbnailState extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Url") ParsedURL url; + + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Width") int width; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_tag("Height") int height; + + public ParsedURL getUrl() + { + return url; + } + + public void setUrl(ParsedURL url) + { + this.url = url; + } + + public int getWidth() + { + return width; + } + + public void setWidth(int width) + { + this.width = width; + } + + public int getHeight() + { + return height; + } + + public void setHeight(int height) + { + this.height = height; + } +} diff --git a/simplCore/src/ecologylab/serialization/library/yahoo/package.html b/simplCore/src/ecologylab/serialization/library/yahoo/package.html index 63dd1d17..34ec64f6 100644 --- a/simplCore/src/ecologylab/serialization/library/yahoo/package.html +++ b/simplCore/src/ecologylab/serialization/library/yahoo/package.html @@ -1,5 +1,5 @@ - -{@link ecologylab.xml.ElementState ElementState} - subclasses that enable translation of XML entities from the -Yahoo web services API. - + +{@link ecologylab.xml.ElementState ElementState} + subclasses that enable translation of XML entities from the +Yahoo web services API. + diff --git a/simplCore/src/ecologylab/serialization/package.html b/simplCore/src/ecologylab/serialization/package.html index d11e66a6..75f49776 100644 --- a/simplCore/src/ecologylab/serialization/package.html +++ b/simplCore/src/ecologylab/serialization/package.html @@ -1,9 +1,9 @@ - -Provides facilities to -translate trees of nested Java objects to equivalent XML DOMs, and -vice versa. The following dated flowchart shows the overall process - of conversion -of Java objects to XML and XML back to Java objects. -

- - + +Provides facilities to +translate trees of nested Java objects to equivalent XML DOMs, and +vice versa. The following dated flowchart shows the overall process + of conversion +of Java objects to XML and XML back to Java objects. +

+ + diff --git a/simplCore/src/ecologylab/serialization/serializers/FormatSerializer.java b/simplCore/src/ecologylab/serialization/serializers/FormatSerializer.java index 8fe9bd54..cc5ae8a0 100644 --- a/simplCore/src/ecologylab/serialization/serializers/FormatSerializer.java +++ b/simplCore/src/ecologylab/serialization/serializers/FormatSerializer.java @@ -1,181 +1,181 @@ -package ecologylab.serialization.serializers; - -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.TranslationContextPool; -import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.formatenums.BinaryFormat; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; -import ecologylab.serialization.serializers.binaryformats.TLVSerializer; -import ecologylab.serialization.serializers.stringformats.BibtexSerializer; -import ecologylab.serialization.serializers.stringformats.JSONSerializer; -import ecologylab.serialization.serializers.stringformats.StringSerializer; -import ecologylab.serialization.serializers.stringformats.XMLSerializer; - -/** - * FormatSerializer. an abstract base class from where format-specific serializers derive. Its main - * use is for exposing the API for serialization methods. It contains helper functions and wrapper - * serialization functions, allowing software developers to use different types of objects for - * serialization, such as System.out, File, StringBuilder, or return serialized data as - * StringBuilder - * - * @author nabeel - * - */ -public abstract class FormatSerializer -{ - /** - * - * @param object - * @param outputStream - * @throws SIMPLTranslationException - */ - public void serialize(Object object, OutputStream outputStream) throws SIMPLTranslationException - { - TranslationContext translationContext = TranslationContextPool.get().acquire(); - serialize(object, outputStream, translationContext); - TranslationContextPool.get().release(translationContext); - } - - public abstract void serialize(Object object, OutputStream outputStream, - TranslationContext translationContext) throws SIMPLTranslationException; - - /** - * - * @param object - * @param outputFile - * @throws SIMPLTranslationException - * @throws IOException - */ - public void serialize(Object object, File outputFile) throws SIMPLTranslationException - { - TranslationContext translationContext = TranslationContextPool.get().acquire(); - serialize(object, outputFile, translationContext); - TranslationContextPool.get().release(translationContext); - } - - public abstract void serialize(Object object, File outputFile, - TranslationContext translationContext) throws SIMPLTranslationException; - - /** - * - * @param object - * @return - */ - protected ClassDescriptor getClassDescriptor(Object object) - { - return ClassDescriptor.getClassDescriptor(object.getClass()); - } - - /** - * - * @param object - * @param translationContext TODO - */ - protected void serializationPostHook(Object object, TranslationContext translationContext) - { - if (object instanceof ISimplSerializationPost) - { - ((ISimplSerializationPost) object).serializationPostHook(translationContext); - } - } - - /** - * - * @param object - * @param translationContext TODO - */ - protected void serializationPreHook(Object object, TranslationContext translationContext) - { - if (object instanceof ISimplSerializationPre) - { - ((ISimplSerializationPre) object).serializationPreHook(translationContext); - } - } - - /** - * - * @param object - * @param translationContext - * @return - */ - protected boolean alreadySerialized(Object object, TranslationContext translationContext) - { - return SimplTypesScope.graphSwitch == GRAPH_SWITCH.ON - && translationContext.alreadyMarshalled(object); - } - - /** - * returns the specific type of serializer based on the input format - * - * @param format - * @return FormatSerializer - * @throws SIMPLTranslationException - */ - public static FormatSerializer getSerializer(Format format) throws SIMPLTranslationException - { - switch (format) - { - case XML: - return new XMLSerializer(); - case JSON: - return new JSONSerializer(); - case TLV: - return new TLVSerializer(); - case BIBTEX: - return new BibtexSerializer(); - default: - throw new SIMPLTranslationException(format + " format not supported"); - } - } - - /** - * returns the specific type of serializer based on the input format - * - * @param format - * @return FormatSerializer - * @throws SIMPLTranslationException - */ - public static StringSerializer getStringSerializer(StringFormat format) - throws SIMPLTranslationException - { - switch (format) - { - case XML: - return new XMLSerializer(); - case JSON: - return new JSONSerializer(); - case BIBTEX: - return new BibtexSerializer(); - default: - throw new SIMPLTranslationException(format + " format not supported"); - } - } - - /** - * returns the specific type of serializer based on the input format - * - * @param format - * @return FormatSerializer - * @throws SIMPLTranslationException - */ - public static FormatSerializer getBinarySerializer(BinaryFormat format) - throws SIMPLTranslationException - { - switch (format) - { - case TLV: - return new TLVSerializer(); - default: - throw new SIMPLTranslationException(format + " format not supported"); - } - } +package ecologylab.serialization.serializers; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.TranslationContextPool; +import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.formatenums.BinaryFormat; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; +import ecologylab.serialization.serializers.binaryformats.TLVSerializer; +import ecologylab.serialization.serializers.stringformats.BibtexSerializer; +import ecologylab.serialization.serializers.stringformats.JSONSerializer; +import ecologylab.serialization.serializers.stringformats.StringSerializer; +import ecologylab.serialization.serializers.stringformats.XMLSerializer; + +/** + * FormatSerializer. an abstract base class from where format-specific serializers derive. Its main + * use is for exposing the API for serialization methods. It contains helper functions and wrapper + * serialization functions, allowing software developers to use different types of objects for + * serialization, such as System.out, File, StringBuilder, or return serialized data as + * StringBuilder + * + * @author nabeel + * + */ +public abstract class FormatSerializer +{ + /** + * + * @param object + * @param outputStream + * @throws SIMPLTranslationException + */ + public void serialize(Object object, OutputStream outputStream) throws SIMPLTranslationException + { + TranslationContext translationContext = TranslationContextPool.get().acquire(); + serialize(object, outputStream, translationContext); + TranslationContextPool.get().release(translationContext); + } + + public abstract void serialize(Object object, OutputStream outputStream, + TranslationContext translationContext) throws SIMPLTranslationException; + + /** + * + * @param object + * @param outputFile + * @throws SIMPLTranslationException + * @throws IOException + */ + public void serialize(Object object, File outputFile) throws SIMPLTranslationException + { + TranslationContext translationContext = TranslationContextPool.get().acquire(); + serialize(object, outputFile, translationContext); + TranslationContextPool.get().release(translationContext); + } + + public abstract void serialize(Object object, File outputFile, + TranslationContext translationContext) throws SIMPLTranslationException; + + /** + * + * @param object + * @return + */ + protected ClassDescriptor getClassDescriptor(Object object) + { + return ClassDescriptor.getClassDescriptor(object.getClass()); + } + + /** + * + * @param object + * @param translationContext TODO + */ + protected void serializationPostHook(Object object, TranslationContext translationContext) + { + if (object instanceof ISimplSerializationPost) + { + ((ISimplSerializationPost) object).serializationPostHook(translationContext); + } + } + + /** + * + * @param object + * @param translationContext TODO + */ + protected void serializationPreHook(Object object, TranslationContext translationContext) + { + if (object instanceof ISimplSerializationPre) + { + ((ISimplSerializationPre) object).serializationPreHook(translationContext); + } + } + + /** + * + * @param object + * @param translationContext + * @return + */ + protected boolean alreadySerialized(Object object, TranslationContext translationContext) + { + return SimplTypesScope.graphSwitch == GRAPH_SWITCH.ON + && translationContext.alreadyMarshalled(object); + } + + /** + * returns the specific type of serializer based on the input format + * + * @param format + * @return FormatSerializer + * @throws SIMPLTranslationException + */ + public static FormatSerializer getSerializer(Format format) throws SIMPLTranslationException + { + switch (format) + { + case XML: + return new XMLSerializer(); + case JSON: + return new JSONSerializer(); + case TLV: + return new TLVSerializer(); + case BIBTEX: + return new BibtexSerializer(); + default: + throw new SIMPLTranslationException(format + " format not supported"); + } + } + + /** + * returns the specific type of serializer based on the input format + * + * @param format + * @return FormatSerializer + * @throws SIMPLTranslationException + */ + public static StringSerializer getStringSerializer(StringFormat format) + throws SIMPLTranslationException + { + switch (format) + { + case XML: + return new XMLSerializer(); + case JSON: + return new JSONSerializer(); + case BIBTEX: + return new BibtexSerializer(); + default: + throw new SIMPLTranslationException(format + " format not supported"); + } + } + + /** + * returns the specific type of serializer based on the input format + * + * @param format + * @return FormatSerializer + * @throws SIMPLTranslationException + */ + public static FormatSerializer getBinarySerializer(BinaryFormat format) + throws SIMPLTranslationException + { + switch (format) + { + case TLV: + return new TLVSerializer(); + default: + throw new SIMPLTranslationException(format + " format not supported"); + } + } } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/serializers/ISimplSerializationPost.java b/simplCore/src/ecologylab/serialization/serializers/ISimplSerializationPost.java index bb5e6e37..7a974fb5 100644 --- a/simplCore/src/ecologylab/serialization/serializers/ISimplSerializationPost.java +++ b/simplCore/src/ecologylab/serialization/serializers/ISimplSerializationPost.java @@ -1,13 +1,13 @@ -package ecologylab.serialization.serializers; - -import ecologylab.serialization.TranslationContext; - -/** - * Interface for applications to plugin functionality after serialization of an object. - * - * @author nabeel - */ -public interface ISimplSerializationPost -{ - void serializationPostHook(TranslationContext translationContext); -} +package ecologylab.serialization.serializers; + +import ecologylab.serialization.TranslationContext; + +/** + * Interface for applications to plugin functionality after serialization of an object. + * + * @author nabeel + */ +public interface ISimplSerializationPost +{ + void serializationPostHook(TranslationContext translationContext); +} diff --git a/simplCore/src/ecologylab/serialization/serializers/ISimplSerializationPre.java b/simplCore/src/ecologylab/serialization/serializers/ISimplSerializationPre.java index b173e99c..10f0377e 100644 --- a/simplCore/src/ecologylab/serialization/serializers/ISimplSerializationPre.java +++ b/simplCore/src/ecologylab/serialization/serializers/ISimplSerializationPre.java @@ -1,13 +1,13 @@ -package ecologylab.serialization.serializers; - -import ecologylab.serialization.TranslationContext; - -/** - * Interface for applications to plugin functionality before serialization of an object. - * - * @author nabeel - */ -public interface ISimplSerializationPre -{ - void serializationPreHook(TranslationContext translationContext); -} +package ecologylab.serialization.serializers; + +import ecologylab.serialization.TranslationContext; + +/** + * Interface for applications to plugin functionality before serialization of an object. + * + * @author nabeel + */ +public interface ISimplSerializationPre +{ + void serializationPreHook(TranslationContext translationContext); +} diff --git a/simplCore/src/ecologylab/serialization/serializers/binaryformats/BinarySerializer.java b/simplCore/src/ecologylab/serialization/serializers/binaryformats/BinarySerializer.java index 33390405..18d8fac5 100644 --- a/simplCore/src/ecologylab/serialization/serializers/binaryformats/BinarySerializer.java +++ b/simplCore/src/ecologylab/serialization/serializers/binaryformats/BinarySerializer.java @@ -1,57 +1,57 @@ -package ecologylab.serialization.serializers.binaryformats; - -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.serializers.FormatSerializer; - -public abstract class BinarySerializer extends FormatSerializer -{ - - @Override - public void serialize(Object object, OutputStream outputStream, - TranslationContext translationContext) throws SIMPLTranslationException - { - serialize(object, new DataOutputStream(outputStream), translationContext); - } - - @Override - public void serialize(Object object, File outputFile, TranslationContext translationContext) - throws SIMPLTranslationException - { - try - { - XMLTools.createParentDirs(outputFile); - - if (outputFile.getParentFile() != null) - translationContext.setBaseDirFile(outputFile.getParentFile()); - - FileOutputStream fStream = new FileOutputStream(outputFile); - serialize(object, fStream, translationContext); - - fStream.close(); - } - catch (IOException e) - { - throw new SIMPLTranslationException("IO Exception: ", e); - } - - } - - /** - * - * @param object - * @param dataOutputStream - * @param translationContext - * @throws SIMPLTranslationException - */ - public abstract void serialize(Object object, DataOutputStream dataOutputStream, - TranslationContext translationContext) throws SIMPLTranslationException; - -} +package ecologylab.serialization.serializers.binaryformats; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.serializers.FormatSerializer; + +public abstract class BinarySerializer extends FormatSerializer +{ + + @Override + public void serialize(Object object, OutputStream outputStream, + TranslationContext translationContext) throws SIMPLTranslationException + { + serialize(object, new DataOutputStream(outputStream), translationContext); + } + + @Override + public void serialize(Object object, File outputFile, TranslationContext translationContext) + throws SIMPLTranslationException + { + try + { + XMLTools.createParentDirs(outputFile); + + if (outputFile.getParentFile() != null) + translationContext.setBaseDirFile(outputFile.getParentFile()); + + FileOutputStream fStream = new FileOutputStream(outputFile); + serialize(object, fStream, translationContext); + + fStream.close(); + } + catch (IOException e) + { + throw new SIMPLTranslationException("IO Exception: ", e); + } + + } + + /** + * + * @param object + * @param dataOutputStream + * @param translationContext + * @throws SIMPLTranslationException + */ + public abstract void serialize(Object object, DataOutputStream dataOutputStream, + TranslationContext translationContext) throws SIMPLTranslationException; + +} diff --git a/simplCore/src/ecologylab/serialization/serializers/binaryformats/TLVSerializer.java b/simplCore/src/ecologylab/serialization/serializers/binaryformats/TLVSerializer.java index ec94b462..5b178c4b 100644 --- a/simplCore/src/ecologylab/serialization/serializers/binaryformats/TLVSerializer.java +++ b/simplCore/src/ecologylab/serialization/serializers/binaryformats/TLVSerializer.java @@ -1,358 +1,358 @@ -package ecologylab.serialization.serializers.binaryformats; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collection; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.FieldTypes; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.annotations.FieldUsage; -import ecologylab.serialization.formatenums.Format; - -/** - * - * @author nabeel - * - */ -public class TLVSerializer extends BinarySerializer implements FieldTypes -{ - - public TLVSerializer() - { - - } - - /** - * - * @param object - * @param dataOutputStream - * @param translationContext - * @throws SIMPLTranslationException - * @throws - * @throws IOException - */ - @Override - public void serialize(Object object, DataOutputStream dataOutputStream, - TranslationContext translationContext) throws SIMPLTranslationException - { - translationContext.resolveGraph(object); - - ClassDescriptor rootObjectClassDescriptor = ClassDescriptor - .getClassDescriptor(object.getClass()); - - try - { - serialize(object, rootObjectClassDescriptor.pseudoFieldDescriptor(), dataOutputStream, - translationContext); - } - catch (IOException e) - { - throw new SIMPLTranslationException("IO Exception occurred", e); - } - } - - /** - * - * @param object - * @param rootObjectFieldDescriptor - * @param dataOutputStream - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - * @throws IOException - */ - private void serialize(Object object, FieldDescriptor rootObjectFieldDescriptor, - DataOutputStream dataOutputStream, TranslationContext translationContext) - throws SIMPLTranslationException, IOException - { - - if (alreadySerialized(object, translationContext)) - { - writeSimplRef(object, rootObjectFieldDescriptor, dataOutputStream); - return; - } - - translationContext.mapObject(object); - - serializationPreHook(object, translationContext); - - ClassDescriptor rootObjectClassDescriptor = getClassDescriptor(object); - - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - DataOutputStream outputBuffer = new DataOutputStream(byteArrayOutputStream); - - int id = rootObjectFieldDescriptor.getTLVId(); - - serializeFields(object, outputBuffer, translationContext, rootObjectClassDescriptor); - - writeHeader(dataOutputStream, byteArrayOutputStream, id); - - serializationPostHook(object, translationContext); - - } - - /** - * - * @param dataOutputStream - * @param buffer - * @param tlvId - * @throws SIMPLTranslationException - */ - private void writeHeader(DataOutputStream dataOutputStream, ByteArrayOutputStream buffer, - int tlvId) throws SIMPLTranslationException - { - try - { - dataOutputStream.writeInt(tlvId); - - dataOutputStream.writeInt(buffer.size()); - buffer.writeTo(dataOutputStream); - } - catch (IOException e) - { - throw new SIMPLTranslationException("IOException", e); - } - } - - /** - * - * @param object - * @param dataOutputStream - * @param translationContext - * @param allFieldDescriptors - * @throws IOException - * @throws SIMPLTranslationException - * @throws IOException - */ - private void serializeFields(Object object, DataOutputStream outputBuffer, - TranslationContext translationContext, - ClassDescriptor classDescriptor) throws SIMPLTranslationException, - IOException - { - if (SimplTypesScope.graphSwitch == GRAPH_SWITCH.ON) - { - if (translationContext.needsHashCode(object)) - { - writeSimplIdAttribute(object, outputBuffer); - } - } - - ArrayList attributeFieldDescriptors = classDescriptor.attributeFieldDescriptors(); - serializeFieldsHelper(outputBuffer, object, translationContext, attributeFieldDescriptors); - ArrayList elementFieldDescriptors = classDescriptor.elementFieldDescriptors(); - serializeFieldsHelper(outputBuffer, object, translationContext, elementFieldDescriptors); - } - - private void serializeFieldsHelper(DataOutputStream outputBuffer, Object object, - TranslationContext translationContext, ArrayList fieldDescriptors) - throws SIMPLTranslationException, IOException - { - for (FieldDescriptor childFd : fieldDescriptors) - { - ByteArrayOutputStream byteArrayOutputStreamCollection = new ByteArrayOutputStream(); - DataOutputStream collectionBuffer = new DataOutputStream(byteArrayOutputStreamCollection); - - switch (childFd.getType()) - { - case SCALAR: - writeValue(object, childFd, outputBuffer, translationContext); - break; - case COMPOSITE_ELEMENT: - Object compositeObject = childFd.getValue(object); - - FieldDescriptor compositeObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( - compositeObject).pseudoFieldDescriptor() - : childFd; - writeWrap(childFd, outputBuffer, byteArrayOutputStreamCollection); - serialize(compositeObject, compositeObjectFieldDescriptor, outputBuffer, translationContext); - writeWrap(childFd, outputBuffer, byteArrayOutputStreamCollection); - break; - case COLLECTION_SCALAR: - case MAP_SCALAR: - Object scalarCollectionObject = childFd.getValue(object); - Collection scalarCollection = XMLTools.getCollection(scalarCollectionObject); - for (Object collectionObject : scalarCollection) - { - writeScalarCollectionLeaf(collectionObject, childFd, collectionBuffer, translationContext); - } - writeWrap(childFd, outputBuffer, byteArrayOutputStreamCollection); - break; - case COLLECTION_ELEMENT: - case MAP_ELEMENT: - Object compositeCollectionObject = childFd.getValue(object); - Collection compositeCollection = XMLTools.getCollection(compositeCollectionObject); - for (Object collectionComposite : compositeCollection) - { - FieldDescriptor collectionObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( - collectionComposite).pseudoFieldDescriptor() - : childFd; - serialize(collectionComposite, collectionObjectFieldDescriptor, collectionBuffer, - translationContext); - } - writeWrap(childFd, outputBuffer, byteArrayOutputStreamCollection); - break; - } - } - } - - /** - * - * @param object - * @param outputBuffer - * @throws IOException - */ - private void writeSimplIdAttribute(Object object, DataOutputStream outputBuffer) - throws IOException - { - outputBuffer.writeInt(TranslationContext.SIMPL_ID.hashCode()); - outputBuffer.writeInt(4); - outputBuffer.writeInt(object.hashCode()); - } - - /** - * - * @param fd - * @param outputBuffer - * @param collectionBuffy - * @throws SIMPLTranslationException - */ - private void writeWrap(FieldDescriptor fd, DataOutputStream outputBuffer, - ByteArrayOutputStream collectionBuffy) throws SIMPLTranslationException - { - try - { - if (fd.isWrapped()) - { - outputBuffer.writeInt(fd.getWrappedTLVId()); - outputBuffer.writeInt(collectionBuffy.size()); - collectionBuffy.writeTo(outputBuffer); - } - else - collectionBuffy.writeTo(outputBuffer); - } - catch (IOException e) - { - throw new SIMPLTranslationException("IOException", e); - } - } - - /** - * - * @param object - * @param fd - * @param outputBuffer - * @param translationContext - * @throws SIMPLTranslationException - */ - private void writeScalarCollectionLeaf(Object object, FieldDescriptor fd, - DataOutputStream outputBuffer, TranslationContext translationContext) - throws SIMPLTranslationException - { - try - { - if (!fd.isDefaultValue(object)) - { - outputBuffer.writeInt(fd.getTLVId()); - - // TODO appendValue in scalar types should be able to append bytes to DataOutputStream. - final StringBuilder buffy = new StringBuilder(); - OutputStream outputStream = new OutputStream() - { - @Override - public void write(int b) throws IOException - { - buffy.append((char) b); - } - }; - - fd.appendCollectionScalarValue(new PrintStream(outputStream), object, translationContext, - Format.TLV); - - ByteArrayOutputStream temp = new ByteArrayOutputStream(); - DataOutputStream tempStream = new DataOutputStream(temp); - tempStream.writeBytes(buffy.toString()); - - outputBuffer.writeInt(tempStream.size()); - temp.writeTo(outputBuffer); - } - } - catch (IOException e) - { - throw new SIMPLTranslationException("IOException", e); - } - } - - /** - * - * @param object - * @param fd - * @param outputBuffer - * @param translationContext - * @throws SIMPLTranslationException - */ - private void writeValue(Object object, FieldDescriptor fd, DataOutputStream outputBuffer, - TranslationContext translationContext) throws SIMPLTranslationException - { - try - { - if (!fd.isDefaultValueFromContext(object)) - { - outputBuffer.writeInt(fd.getTLVId()); - - // TODO appendValue in scalar types should be able to append bytes to DataOutputStream. - final StringBuilder buffy = new StringBuilder(); - OutputStream outputStream = new OutputStream() - { - @Override - public void write(int b) throws IOException - { - buffy.append((char) b); - } - }; - - fd.appendValue(new PrintStream(outputStream), object, translationContext, Format.TLV); - - ByteArrayOutputStream temp = new ByteArrayOutputStream(); - DataOutputStream tempStream = new DataOutputStream(temp); - tempStream.writeBytes(buffy.toString()); - - outputBuffer.writeInt(tempStream.size()); - temp.writeTo(outputBuffer); - } - } - catch (IOException e) - { - throw new SIMPLTranslationException("IOException", e); - } - } - - /** - * - * @param object - * @param rootObjectFieldDescriptor - * @param dataOutputStream - * @throws IOException - * @throws SIMPLTranslationException - */ - private void writeSimplRef(Object object, FieldDescriptor fd, DataOutputStream outputStream) - throws IOException, SIMPLTranslationException - { - ByteArrayOutputStream simplRefData = new ByteArrayOutputStream(); - DataOutputStream outputBuffer = new DataOutputStream(simplRefData); - outputBuffer.writeInt(TranslationContext.SIMPL_REF.hashCode()); - outputBuffer.writeInt(4); - outputBuffer.writeInt(object.hashCode()); - - writeHeader(outputStream, simplRefData, fd.getTLVId()); - } -} +package ecologylab.serialization.serializers.binaryformats; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Collection; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.FieldTypes; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.FieldUsage; +import ecologylab.serialization.formatenums.Format; + +/** + * + * @author nabeel + * + */ +public class TLVSerializer extends BinarySerializer implements FieldTypes +{ + + public TLVSerializer() + { + + } + + /** + * + * @param object + * @param dataOutputStream + * @param translationContext + * @throws SIMPLTranslationException + * @throws + * @throws IOException + */ + @Override + public void serialize(Object object, DataOutputStream dataOutputStream, + TranslationContext translationContext) throws SIMPLTranslationException + { + translationContext.resolveGraph(object); + + ClassDescriptor rootObjectClassDescriptor = ClassDescriptor + .getClassDescriptor(object.getClass()); + + try + { + serialize(object, rootObjectClassDescriptor.pseudoFieldDescriptor(), dataOutputStream, + translationContext); + } + catch (IOException e) + { + throw new SIMPLTranslationException("IO Exception occurred", e); + } + } + + /** + * + * @param object + * @param rootObjectFieldDescriptor + * @param dataOutputStream + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + * @throws IOException + */ + private void serialize(Object object, FieldDescriptor rootObjectFieldDescriptor, + DataOutputStream dataOutputStream, TranslationContext translationContext) + throws SIMPLTranslationException, IOException + { + + if (alreadySerialized(object, translationContext)) + { + writeSimplRef(object, rootObjectFieldDescriptor, dataOutputStream); + return; + } + + translationContext.mapObject(object); + + serializationPreHook(object, translationContext); + + ClassDescriptor rootObjectClassDescriptor = getClassDescriptor(object); + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + DataOutputStream outputBuffer = new DataOutputStream(byteArrayOutputStream); + + int id = rootObjectFieldDescriptor.getTLVId(); + + serializeFields(object, outputBuffer, translationContext, rootObjectClassDescriptor); + + writeHeader(dataOutputStream, byteArrayOutputStream, id); + + serializationPostHook(object, translationContext); + + } + + /** + * + * @param dataOutputStream + * @param buffer + * @param tlvId + * @throws SIMPLTranslationException + */ + private void writeHeader(DataOutputStream dataOutputStream, ByteArrayOutputStream buffer, + int tlvId) throws SIMPLTranslationException + { + try + { + dataOutputStream.writeInt(tlvId); + + dataOutputStream.writeInt(buffer.size()); + buffer.writeTo(dataOutputStream); + } + catch (IOException e) + { + throw new SIMPLTranslationException("IOException", e); + } + } + + /** + * + * @param object + * @param dataOutputStream + * @param translationContext + * @param allFieldDescriptors + * @throws IOException + * @throws SIMPLTranslationException + * @throws IOException + */ + private void serializeFields(Object object, DataOutputStream outputBuffer, + TranslationContext translationContext, + ClassDescriptor classDescriptor) throws SIMPLTranslationException, + IOException + { + if (SimplTypesScope.graphSwitch == GRAPH_SWITCH.ON) + { + if (translationContext.needsHashCode(object)) + { + writeSimplIdAttribute(object, outputBuffer); + } + } + + ArrayList attributeFieldDescriptors = classDescriptor.attributeFieldDescriptors(); + serializeFieldsHelper(outputBuffer, object, translationContext, attributeFieldDescriptors); + ArrayList elementFieldDescriptors = classDescriptor.elementFieldDescriptors(); + serializeFieldsHelper(outputBuffer, object, translationContext, elementFieldDescriptors); + } + + private void serializeFieldsHelper(DataOutputStream outputBuffer, Object object, + TranslationContext translationContext, ArrayList fieldDescriptors) + throws SIMPLTranslationException, IOException + { + for (FieldDescriptor childFd : fieldDescriptors) + { + ByteArrayOutputStream byteArrayOutputStreamCollection = new ByteArrayOutputStream(); + DataOutputStream collectionBuffer = new DataOutputStream(byteArrayOutputStreamCollection); + + switch (childFd.getType()) + { + case SCALAR: + writeValue(object, childFd, outputBuffer, translationContext); + break; + case COMPOSITE_ELEMENT: + Object compositeObject = childFd.getValue(object); + + FieldDescriptor compositeObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( + compositeObject).pseudoFieldDescriptor() + : childFd; + writeWrap(childFd, outputBuffer, byteArrayOutputStreamCollection); + serialize(compositeObject, compositeObjectFieldDescriptor, outputBuffer, translationContext); + writeWrap(childFd, outputBuffer, byteArrayOutputStreamCollection); + break; + case COLLECTION_SCALAR: + case MAP_SCALAR: + Object scalarCollectionObject = childFd.getValue(object); + Collection scalarCollection = XMLTools.getCollection(scalarCollectionObject); + for (Object collectionObject : scalarCollection) + { + writeScalarCollectionLeaf(collectionObject, childFd, collectionBuffer, translationContext); + } + writeWrap(childFd, outputBuffer, byteArrayOutputStreamCollection); + break; + case COLLECTION_ELEMENT: + case MAP_ELEMENT: + Object compositeCollectionObject = childFd.getValue(object); + Collection compositeCollection = XMLTools.getCollection(compositeCollectionObject); + for (Object collectionComposite : compositeCollection) + { + FieldDescriptor collectionObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( + collectionComposite).pseudoFieldDescriptor() + : childFd; + serialize(collectionComposite, collectionObjectFieldDescriptor, collectionBuffer, + translationContext); + } + writeWrap(childFd, outputBuffer, byteArrayOutputStreamCollection); + break; + } + } + } + + /** + * + * @param object + * @param outputBuffer + * @throws IOException + */ + private void writeSimplIdAttribute(Object object, DataOutputStream outputBuffer) + throws IOException + { + outputBuffer.writeInt(TranslationContext.SIMPL_ID.hashCode()); + outputBuffer.writeInt(4); + outputBuffer.writeInt(object.hashCode()); + } + + /** + * + * @param fd + * @param outputBuffer + * @param collectionBuffy + * @throws SIMPLTranslationException + */ + private void writeWrap(FieldDescriptor fd, DataOutputStream outputBuffer, + ByteArrayOutputStream collectionBuffy) throws SIMPLTranslationException + { + try + { + if (fd.isWrapped()) + { + outputBuffer.writeInt(fd.getWrappedTLVId()); + outputBuffer.writeInt(collectionBuffy.size()); + collectionBuffy.writeTo(outputBuffer); + } + else + collectionBuffy.writeTo(outputBuffer); + } + catch (IOException e) + { + throw new SIMPLTranslationException("IOException", e); + } + } + + /** + * + * @param object + * @param fd + * @param outputBuffer + * @param translationContext + * @throws SIMPLTranslationException + */ + private void writeScalarCollectionLeaf(Object object, FieldDescriptor fd, + DataOutputStream outputBuffer, TranslationContext translationContext) + throws SIMPLTranslationException + { + try + { + if (!fd.isDefaultValue(object)) + { + outputBuffer.writeInt(fd.getTLVId()); + + // TODO appendValue in scalar types should be able to append bytes to DataOutputStream. + final StringBuilder buffy = new StringBuilder(); + OutputStream outputStream = new OutputStream() + { + @Override + public void write(int b) throws IOException + { + buffy.append((char) b); + } + }; + + fd.appendCollectionScalarValue(new PrintStream(outputStream), object, translationContext, + Format.TLV); + + ByteArrayOutputStream temp = new ByteArrayOutputStream(); + DataOutputStream tempStream = new DataOutputStream(temp); + tempStream.writeBytes(buffy.toString()); + + outputBuffer.writeInt(tempStream.size()); + temp.writeTo(outputBuffer); + } + } + catch (IOException e) + { + throw new SIMPLTranslationException("IOException", e); + } + } + + /** + * + * @param object + * @param fd + * @param outputBuffer + * @param translationContext + * @throws SIMPLTranslationException + */ + private void writeValue(Object object, FieldDescriptor fd, DataOutputStream outputBuffer, + TranslationContext translationContext) throws SIMPLTranslationException + { + try + { + if (!fd.isDefaultValueFromContext(object)) + { + outputBuffer.writeInt(fd.getTLVId()); + + // TODO appendValue in scalar types should be able to append bytes to DataOutputStream. + final StringBuilder buffy = new StringBuilder(); + OutputStream outputStream = new OutputStream() + { + @Override + public void write(int b) throws IOException + { + buffy.append((char) b); + } + }; + + fd.appendValue(new PrintStream(outputStream), object, translationContext, Format.TLV); + + ByteArrayOutputStream temp = new ByteArrayOutputStream(); + DataOutputStream tempStream = new DataOutputStream(temp); + tempStream.writeBytes(buffy.toString()); + + outputBuffer.writeInt(tempStream.size()); + temp.writeTo(outputBuffer); + } + } + catch (IOException e) + { + throw new SIMPLTranslationException("IOException", e); + } + } + + /** + * + * @param object + * @param rootObjectFieldDescriptor + * @param dataOutputStream + * @throws IOException + * @throws SIMPLTranslationException + */ + private void writeSimplRef(Object object, FieldDescriptor fd, DataOutputStream outputStream) + throws IOException, SIMPLTranslationException + { + ByteArrayOutputStream simplRefData = new ByteArrayOutputStream(); + DataOutputStream outputBuffer = new DataOutputStream(simplRefData); + outputBuffer.writeInt(TranslationContext.SIMPL_REF.hashCode()); + outputBuffer.writeInt(4); + outputBuffer.writeInt(object.hashCode()); + + writeHeader(outputStream, simplRefData, fd.getTLVId()); + } +} diff --git a/simplCore/src/ecologylab/serialization/serializers/stringformats/BibtexSerializer.java b/simplCore/src/ecologylab/serialization/serializers/stringformats/BibtexSerializer.java index f7b326d7..f4c52a95 100644 --- a/simplCore/src/ecologylab/serialization/serializers/stringformats/BibtexSerializer.java +++ b/simplCore/src/ecologylab/serialization/serializers/stringformats/BibtexSerializer.java @@ -1,319 +1,319 @@ -package ecologylab.serialization.serializers.stringformats; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.FieldTypes; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.annotations.FieldUsage; -import ecologylab.serialization.formatenums.Format; - -/** - * - * @author nabeel - */ -public class BibtexSerializer extends StringSerializer implements FieldTypes -{ - - public BibtexSerializer() - { - } - - @Override - public void serialize(Object object, Appendable appendable, TranslationContext translationContext) - throws SIMPLTranslationException - { - translationContext.resolveGraph(object); - - ClassDescriptor rootObjectClassDescriptor = ClassDescriptor - .getClassDescriptor(object.getClass()); - - try - { - serialize(object, rootObjectClassDescriptor.pseudoFieldDescriptor(), appendable, - translationContext); - } - catch (IOException e) - { - throw new SIMPLTranslationException("IO Exception occurred", e); - } - } - - /** - * - * @param object - * @param rootObjectFieldDescriptor - * @param appendable - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - private void serialize(Object object, FieldDescriptor rootObjectFieldDescriptor, - Appendable appendable, TranslationContext translationContext) - throws SIMPLTranslationException, IOException - { - serializationPreHook(object, translationContext); - - writeObjectStart(rootObjectFieldDescriptor, appendable); - - ArrayList allFieldDescriptors = getClassDescriptor(object) - .allFieldDescriptors(); - - serializeFields(object, appendable, translationContext, allFieldDescriptors); - - writeClose(appendable); - - serializationPostHook(object, translationContext); - } - - /** - * - * @param object - * @param appendable - * @param translationContext - * @param allFieldDescriptors - * @throws IOException - * @throws SIMPLTranslationException - */ - private void serializeFields(Object object, Appendable appendable, - TranslationContext translationContext, - ArrayList allFieldDescriptors) throws IOException, - SIMPLTranslationException - { - int numOfFields = 0; - - for (FieldDescriptor childFd : allFieldDescriptors) - { - switch (childFd.getType()) - { - case SCALAR: - serializeScalar(object, childFd, appendable, translationContext); - break; - case COMPOSITE_ELEMENT: - serializeComposite(object, appendable, translationContext, childFd); - break; - case COLLECTION_SCALAR: - case MAP_SCALAR: - serializeScalarCollection(object, appendable, translationContext, childFd); - break; - case COLLECTION_ELEMENT: - case MAP_ELEMENT: - if (!childFd.isPolymorphic()) - serializeCompositeCollection(object, appendable, translationContext, childFd); - break; - } - - if (++numOfFields < allFieldDescriptors.size()) - appendable.append(','); - } - } - - /** - * - * @param object - * @param fd - * @param appendable - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - private void serializeScalar(Object object, FieldDescriptor fd, Appendable appendable, - TranslationContext translationContext) throws SIMPLTranslationException, IOException - { - writeBibtexAttribute(object, fd, appendable, translationContext); - } - - private void serializeComposite(Object object, Appendable appendable, - TranslationContext translationContext, FieldDescriptor fd) throws SIMPLTranslationException, - IOException - { - Object compositeObject = fd.getValue(object); - - FieldDescriptor compositeAsScalarFD = getClassDescriptor(compositeObject) - .getScalarValueFieldDescripotor(); - - if (compositeAsScalarFD != null) - { - writeScalarBibtexAttribute(compositeObject, compositeAsScalarFD, appendable, translationContext); - } - } - - private void writeScalarBibtexAttribute(Object object, FieldDescriptor fd, Appendable appendable, - TranslationContext translationContext) throws SIMPLTranslationException - { - if (!fd.isDefaultValueFromContext(object)) - { - fd.appendValue(appendable, object, translationContext, Format.BIBTEX); - } - } - - /** - * - * @param object - * @param fd - * @param appendable - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - private void writeBibtexAttribute(Object object, FieldDescriptor fd, Appendable appendable, - TranslationContext translationContext) throws SIMPLTranslationException, IOException - { - if (!fd.isDefaultValueFromContext(object)) - { - if (!fd.isBibtexKey()) - { - appendable.append(fd.getBibtexTagName()); - appendable.append('='); - appendable.append('{'); - } - } - - fd.appendValue(appendable, object, translationContext, Format.BIBTEX); - - if (!fd.isBibtexKey()) - appendable.append('}'); - } - - /** - * - * @param object - * @param appendable - * @param translationContext - * @param fd - * @throws IOException - * @throws SIMPLTranslationException - */ - private void serializeCompositeCollection(Object object, Appendable appendable, - TranslationContext translationContext, FieldDescriptor fd) throws IOException, - SIMPLTranslationException - { - Object scalarCollectionObject = fd.getValue(object); - Collection scalarCollection = XMLTools.getCollection(scalarCollectionObject); - - String delim = "author".equals(fd.getBibtexTagName()) ? " and " : translationContext - .getDelimiter(); - - if (scalarCollection.size() > 0) - { - int numberOfItems = 0; - - writeCollectionStart(fd, appendable); - for (Object collectionObject : scalarCollection) - { - FieldDescriptor compositeAsScalarFD = getClassDescriptor(collectionObject) - .getScalarValueFieldDescripotor(); - - if (compositeAsScalarFD != null) - { - writeScalarBibtexAttribute(collectionObject, compositeAsScalarFD, appendable, - translationContext); - } - - if (++numberOfItems < scalarCollection.size()) - appendable.append(delim); - } - writeCollectionEnd(appendable); - } - } - - /** - * - * @param object - * @param appendable - * @param translationContext - * @param fd - * @throws IOException - * @throws SIMPLTranslationException - */ - private void serializeScalarCollection(Object object, Appendable appendable, - TranslationContext translationContext, FieldDescriptor fd) throws IOException, - SIMPLTranslationException - { - Object scalarCollectionObject = fd.getValue(object); - Collection scalarCollection = XMLTools.getCollection(scalarCollectionObject); - - String delim = "author".equals(fd.getBibtexTagName()) ? " and " : translationContext - .getDelimiter(); - - if (scalarCollection.size() > 0) - { - int numberOfItems = 0; - - writeCollectionStart(fd, appendable); - for (Object collectionObject : scalarCollection) - { - writeCollectionScalar(collectionObject, fd, appendable, translationContext); - if (++numberOfItems < scalarCollection.size()) - appendable.append(delim); - } - writeCollectionEnd(appendable); - } - } - - /** - * - * @param fd - * @param appendable - * @throws IOException - */ - private void writeCollectionStart(FieldDescriptor fd, Appendable appendable) throws IOException - { - appendable.append(fd.getTagName()); - appendable.append('='); - appendable.append("{"); - } - - /** - * - * @param appendable - * @throws IOException - */ - private void writeCollectionEnd(Appendable appendable) throws IOException - { - appendable.append("}"); - } - - /** - * - * @param collectionObject - * @param fd - * @param appendable - * @param translationContext - * @throws SIMPLTranslationException - */ - private void writeCollectionScalar(Object collectionObject, FieldDescriptor fd, - Appendable appendable, TranslationContext translationContext) - throws SIMPLTranslationException - { - fd.appendCollectionScalarValue(appendable, collectionObject, translationContext, Format.BIBTEX); - } - - /** - * - * @param appendable - * @throws IOException - */ - private void writeClose(Appendable appendable) throws IOException - { - appendable.append('}'); - } - - /** - * - * @param fd - * @param appendable - * @throws IOException - */ - private void writeObjectStart(FieldDescriptor fd, Appendable appendable) throws IOException - { - appendable.append('@'); - appendable.append(fd.getBibtexTagName()); - appendable.append('{'); - } -} +package ecologylab.serialization.serializers.stringformats; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.FieldTypes; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.FieldUsage; +import ecologylab.serialization.formatenums.Format; + +/** + * + * @author nabeel + */ +public class BibtexSerializer extends StringSerializer implements FieldTypes +{ + + public BibtexSerializer() + { + } + + @Override + public void serialize(Object object, Appendable appendable, TranslationContext translationContext) + throws SIMPLTranslationException + { + translationContext.resolveGraph(object); + + ClassDescriptor rootObjectClassDescriptor = ClassDescriptor + .getClassDescriptor(object.getClass()); + + try + { + serialize(object, rootObjectClassDescriptor.pseudoFieldDescriptor(), appendable, + translationContext); + } + catch (IOException e) + { + throw new SIMPLTranslationException("IO Exception occurred", e); + } + } + + /** + * + * @param object + * @param rootObjectFieldDescriptor + * @param appendable + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + private void serialize(Object object, FieldDescriptor rootObjectFieldDescriptor, + Appendable appendable, TranslationContext translationContext) + throws SIMPLTranslationException, IOException + { + serializationPreHook(object, translationContext); + + writeObjectStart(rootObjectFieldDescriptor, appendable); + + ArrayList allFieldDescriptors = getClassDescriptor(object) + .allFieldDescriptors(); + + serializeFields(object, appendable, translationContext, allFieldDescriptors); + + writeClose(appendable); + + serializationPostHook(object, translationContext); + } + + /** + * + * @param object + * @param appendable + * @param translationContext + * @param allFieldDescriptors + * @throws IOException + * @throws SIMPLTranslationException + */ + private void serializeFields(Object object, Appendable appendable, + TranslationContext translationContext, + ArrayList allFieldDescriptors) throws IOException, + SIMPLTranslationException + { + int numOfFields = 0; + + for (FieldDescriptor childFd : allFieldDescriptors) + { + switch (childFd.getType()) + { + case SCALAR: + serializeScalar(object, childFd, appendable, translationContext); + break; + case COMPOSITE_ELEMENT: + serializeComposite(object, appendable, translationContext, childFd); + break; + case COLLECTION_SCALAR: + case MAP_SCALAR: + serializeScalarCollection(object, appendable, translationContext, childFd); + break; + case COLLECTION_ELEMENT: + case MAP_ELEMENT: + if (!childFd.isPolymorphic()) + serializeCompositeCollection(object, appendable, translationContext, childFd); + break; + } + + if (++numOfFields < allFieldDescriptors.size()) + appendable.append(','); + } + } + + /** + * + * @param object + * @param fd + * @param appendable + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + private void serializeScalar(Object object, FieldDescriptor fd, Appendable appendable, + TranslationContext translationContext) throws SIMPLTranslationException, IOException + { + writeBibtexAttribute(object, fd, appendable, translationContext); + } + + private void serializeComposite(Object object, Appendable appendable, + TranslationContext translationContext, FieldDescriptor fd) throws SIMPLTranslationException, + IOException + { + Object compositeObject = fd.getValue(object); + + FieldDescriptor compositeAsScalarFD = getClassDescriptor(compositeObject) + .getScalarValueFieldDescripotor(); + + if (compositeAsScalarFD != null) + { + writeScalarBibtexAttribute(compositeObject, compositeAsScalarFD, appendable, translationContext); + } + } + + private void writeScalarBibtexAttribute(Object object, FieldDescriptor fd, Appendable appendable, + TranslationContext translationContext) throws SIMPLTranslationException + { + if (!fd.isDefaultValueFromContext(object)) + { + fd.appendValue(appendable, object, translationContext, Format.BIBTEX); + } + } + + /** + * + * @param object + * @param fd + * @param appendable + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + private void writeBibtexAttribute(Object object, FieldDescriptor fd, Appendable appendable, + TranslationContext translationContext) throws SIMPLTranslationException, IOException + { + if (!fd.isDefaultValueFromContext(object)) + { + if (!fd.isBibtexKey()) + { + appendable.append(fd.getBibtexTagName()); + appendable.append('='); + appendable.append('{'); + } + } + + fd.appendValue(appendable, object, translationContext, Format.BIBTEX); + + if (!fd.isBibtexKey()) + appendable.append('}'); + } + + /** + * + * @param object + * @param appendable + * @param translationContext + * @param fd + * @throws IOException + * @throws SIMPLTranslationException + */ + private void serializeCompositeCollection(Object object, Appendable appendable, + TranslationContext translationContext, FieldDescriptor fd) throws IOException, + SIMPLTranslationException + { + Object scalarCollectionObject = fd.getValue(object); + Collection scalarCollection = XMLTools.getCollection(scalarCollectionObject); + + String delim = "author".equals(fd.getBibtexTagName()) ? " and " : translationContext + .getDelimiter(); + + if (scalarCollection.size() > 0) + { + int numberOfItems = 0; + + writeCollectionStart(fd, appendable); + for (Object collectionObject : scalarCollection) + { + FieldDescriptor compositeAsScalarFD = getClassDescriptor(collectionObject) + .getScalarValueFieldDescripotor(); + + if (compositeAsScalarFD != null) + { + writeScalarBibtexAttribute(collectionObject, compositeAsScalarFD, appendable, + translationContext); + } + + if (++numberOfItems < scalarCollection.size()) + appendable.append(delim); + } + writeCollectionEnd(appendable); + } + } + + /** + * + * @param object + * @param appendable + * @param translationContext + * @param fd + * @throws IOException + * @throws SIMPLTranslationException + */ + private void serializeScalarCollection(Object object, Appendable appendable, + TranslationContext translationContext, FieldDescriptor fd) throws IOException, + SIMPLTranslationException + { + Object scalarCollectionObject = fd.getValue(object); + Collection scalarCollection = XMLTools.getCollection(scalarCollectionObject); + + String delim = "author".equals(fd.getBibtexTagName()) ? " and " : translationContext + .getDelimiter(); + + if (scalarCollection.size() > 0) + { + int numberOfItems = 0; + + writeCollectionStart(fd, appendable); + for (Object collectionObject : scalarCollection) + { + writeCollectionScalar(collectionObject, fd, appendable, translationContext); + if (++numberOfItems < scalarCollection.size()) + appendable.append(delim); + } + writeCollectionEnd(appendable); + } + } + + /** + * + * @param fd + * @param appendable + * @throws IOException + */ + private void writeCollectionStart(FieldDescriptor fd, Appendable appendable) throws IOException + { + appendable.append(fd.getTagName()); + appendable.append('='); + appendable.append("{"); + } + + /** + * + * @param appendable + * @throws IOException + */ + private void writeCollectionEnd(Appendable appendable) throws IOException + { + appendable.append("}"); + } + + /** + * + * @param collectionObject + * @param fd + * @param appendable + * @param translationContext + * @throws SIMPLTranslationException + */ + private void writeCollectionScalar(Object collectionObject, FieldDescriptor fd, + Appendable appendable, TranslationContext translationContext) + throws SIMPLTranslationException + { + fd.appendCollectionScalarValue(appendable, collectionObject, translationContext, Format.BIBTEX); + } + + /** + * + * @param appendable + * @throws IOException + */ + private void writeClose(Appendable appendable) throws IOException + { + appendable.append('}'); + } + + /** + * + * @param fd + * @param appendable + * @throws IOException + */ + private void writeObjectStart(FieldDescriptor fd, Appendable appendable) throws IOException + { + appendable.append('@'); + appendable.append(fd.getBibtexTagName()); + appendable.append('{'); + } +} diff --git a/simplCore/src/ecologylab/serialization/serializers/stringformats/JSONSerializer.java b/simplCore/src/ecologylab/serialization/serializers/stringformats/JSONSerializer.java index 65b829d8..0226f956 100644 --- a/simplCore/src/ecologylab/serialization/serializers/stringformats/JSONSerializer.java +++ b/simplCore/src/ecologylab/serialization/serializers/stringformats/JSONSerializer.java @@ -1,503 +1,520 @@ -package ecologylab.serialization.serializers.stringformats; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.FieldTypes; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.annotations.FieldUsage; -import ecologylab.serialization.formatenums.Format; - -/*** - * JSONSerializaton. Guides serialization of data in JSON. Contains code that is specific to - * creating a valid JSON of the provided object. Supports graph handling. - * - * @author nabeel - * - */ -public class JSONSerializer extends StringSerializer implements FieldTypes -{ - private int numOfFields; - - public JSONSerializer() - { - - } - - @Override - public void serialize(Object object, Appendable appendable, TranslationContext translationContext) - throws SIMPLTranslationException - { - translationContext.resolveGraph(object); - - ClassDescriptor rootObjectClassDescriptor = ClassDescriptor - .getClassDescriptor(object.getClass()); - - try - { - writeStart(appendable); - - serialize(object, rootObjectClassDescriptor.pseudoFieldDescriptor(), appendable, - translationContext, true); - - writeClose(appendable); - } - catch (IOException e) - { - throw new SIMPLTranslationException("IO Exception occurred", e); - } - } - - /** - * - * @param object - * @param rootObjectFieldDescriptor - * @param appendable - * @param translationContext - * @param withTag - * @throws SIMPLTranslationException - * @throws IOException - */ - private void serialize(Object object, FieldDescriptor rootObjectFieldDescriptor, - Appendable appendable, TranslationContext translationContext, boolean withTag) - throws SIMPLTranslationException, IOException - { - if (alreadySerialized(object, translationContext)) - { - writeSimplRef(object, rootObjectFieldDescriptor, withTag, appendable, translationContext); - return; - } - - translationContext.mapObject(object); - - serializationPreHook(object, translationContext); - - writeObjectStart(rootObjectFieldDescriptor, appendable, withTag); - - //numOfFields = 0; - - ClassDescriptor classDescriptor = getClassDescriptor(object); - - serializeFields(object, appendable, translationContext, classDescriptor); - - writeClose(appendable); - - serializationPostHook(object, translationContext); - } - - /** - * - * @param object - * @param appendable - * @param translationContext - * @param allFieldDescriptors - * @throws SIMPLTranslationException - * @throws IOException - */ - private void serializeFields(Object object, Appendable appendable, - TranslationContext translationContext, - ClassDescriptor classDescriptor) throws SIMPLTranslationException, - IOException - { - ArrayList allFieldDescriptors = classDescriptor.allFieldDescriptors(); - - if (SimplTypesScope.graphSwitch == GRAPH_SWITCH.ON) - { - if (translationContext.needsHashCode(object)) - { - writeSimplIdAttribute(object, appendable, allFieldDescriptors.size() <= 0); - } - } - - ArrayList attributeFieldDescriptors = classDescriptor.attributeFieldDescriptors(); - int numOfFields = serializeFieldsHelper(appendable, object, translationContext, attributeFieldDescriptors, 0); - ArrayList elementFieldDescriptors = classDescriptor.elementFieldDescriptors(); - serializeFieldsHelper(appendable, object, translationContext, elementFieldDescriptors,numOfFields); - } - - private int serializeFieldsHelper(Appendable appendable, Object object, - TranslationContext translationContext, - ArrayList fieldDescriptorList, int numOfFields) throws SIMPLTranslationException, - IOException - { - - for (FieldDescriptor childFd : fieldDescriptorList) - { - if (isSerializable(childFd, object)) - { - if (numOfFields++ > 0) - appendable.append(','); - - switch (childFd.getType()) - { - case SCALAR: - serializeScalar(object, childFd, appendable, translationContext); - break; - case COMPOSITE_ELEMENT: - serializeComposite(object, appendable, translationContext, childFd); - break; - case COLLECTION_SCALAR: - case MAP_SCALAR: - serializeScalarCollection(object, appendable, translationContext, childFd); - break; - case COLLECTION_ELEMENT: - case MAP_ELEMENT: - if (childFd.isPolymorphic()) - serializePolymorphicCollection(object, appendable, translationContext, childFd); - else - serializeCompositeCollection(object, appendable, translationContext, childFd); - break; - } - } - } - return numOfFields; - } - - /** - * check if the field is of default value or null. we don't have to serialize that field - * - * @param childFd - * @param object - * @return - * @throws SIMPLTranslationException - */ - private boolean isSerializable(FieldDescriptor childFd, Object object) - throws SIMPLTranslationException - { - switch (childFd.getType()) - { - case SCALAR: - if (childFd.isDefaultValueFromContext(object)) - return false; - break; - case COMPOSITE_ELEMENT: - case COLLECTION_ELEMENT: - case MAP_ELEMENT: - Object obj = childFd.getValue(object); - if (obj == null) - return false; - break; - case COLLECTION_SCALAR: - case MAP_SCALAR: - Object scalarCollectionObject = childFd.getValue(object); - Collection scalarCollection = XMLTools.getCollection(scalarCollectionObject); - if (scalarCollection == null || scalarCollection.size() <= 0) - return false; - break; - } - - return true; - } - - /** - * - * @param object - * @param appendable - * @param translationContext - * @param childFd - * @throws SIMPLTranslationException - * @throws IOException - */ - private void serializeComposite(Object object, Appendable appendable, - TranslationContext translationContext, FieldDescriptor childFd) - throws SIMPLTranslationException, IOException - { - Object compositeObject = childFd.getValue(object); - FieldDescriptor compositeObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( - compositeObject).pseudoFieldDescriptor() : childFd; - serialize(compositeObject, compositeObjectFieldDescriptor, appendable, translationContext, true); - } - - /** - * - * @param object - * @param appendable - * @param translationContext - * @param childFd - * @throws IOException - * @throws SIMPLTranslationException - */ - private void serializeCompositeCollection(Object object, Appendable appendable, - TranslationContext translationContext, FieldDescriptor childFd) throws IOException, - SIMPLTranslationException - { - Object collectionObject = childFd.getValue(object); - Collection compositeCollection = XMLTools.getCollection(collectionObject); - - if(compositeCollection != null) - { - int numberOfItems = 0; - - writeWrap(childFd, appendable, false); - writeCollectionStart(childFd, appendable); - for (Object collectionComposite : compositeCollection) - { - FieldDescriptor collectionObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( - collectionComposite).pseudoFieldDescriptor() - : childFd; - - serialize(collectionComposite, collectionObjectFieldDescriptor, appendable, - translationContext, false); - - if (++numberOfItems < compositeCollection.size()) - appendable.append(','); - } - writeCollectionEnd(appendable); - writeWrap(childFd, appendable, true); - } - } - - /** - * - * @param object - * @param appendable - * @param translationContext - * @param childFd - * @throws IOException - * @throws SIMPLTranslationException - */ - private void serializePolymorphicCollection(Object object, Appendable appendable, - TranslationContext translationContext, FieldDescriptor childFd) throws IOException, - SIMPLTranslationException - { - Object collectionObject = childFd.getValue(object); - Collection compositeCollection = XMLTools.getCollection(collectionObject); - int numberOfItems = 0; - - if(compositeCollection != null) - { - writePolymorphicCollectionStart(childFd, appendable); - for (Object collectionComposite : compositeCollection) - { - FieldDescriptor collectionObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( - collectionComposite).pseudoFieldDescriptor() - : childFd; - - writeStart(appendable); - serialize(collectionComposite, collectionObjectFieldDescriptor, appendable, - translationContext, true); - writeClose(appendable); - - if (++numberOfItems < compositeCollection.size()) - appendable.append(','); - } - writeCollectionEnd(appendable); - } - } - - /** - * - * @param object - * @param appendable - * @param translationContext - * @param childFd - * @throws IOException - * @throws SIMPLTranslationException - */ - private void serializeScalarCollection(Object object, Appendable appendable, - TranslationContext translationContext, FieldDescriptor childFd) throws IOException, - SIMPLTranslationException - { - Object scalarCollectionObject = childFd.getValue(object); - Collection scalarCollection = XMLTools.getCollection(scalarCollectionObject); - int numberOfItems = 0; - - if(scalarCollection != null) - { - writeWrap(childFd, appendable, false); - writeCollectionStart(childFd, appendable); - for (Object collectionObject : scalarCollection) - { - writeCollectionScalar(collectionObject, childFd, appendable, translationContext); - if (++numberOfItems < scalarCollection.size()) - appendable.append(','); - } - writeCollectionEnd(appendable); - writeWrap(childFd, appendable, true); - } - } - - /** - * - * @param object - * @param fd - * @param appendable - * @param translationContext - * @throws IOException - * @throws SIMPLTranslationException - */ - private void serializeScalar(Object object, FieldDescriptor fd, Appendable appendable, - TranslationContext translationContext) throws IOException, SIMPLTranslationException - { - appendable.append('"'); - appendable.append(fd.getTagName()); - appendable.append('"'); - appendable.append(':'); - appendable.append('"'); - fd.appendValue(appendable, object, translationContext, Format.JSON); - appendable.append('"'); - } - - /** - * - * @param appendable - * @throws IOException - */ - private void writeCollectionEnd(Appendable appendable) throws IOException - { - appendable.append(']'); - } - - private void writeCollectionStart(FieldDescriptor fd, Appendable appendable) throws IOException - { - appendable.append('"').append(fd.elementStart()).append('"'); - appendable.append(':'); - appendable.append('['); - } - - /** - * - * @param fd - * @param appendable - * @throws IOException - */ - private void writePolymorphicCollectionStart(FieldDescriptor fd, Appendable appendable) - throws IOException - { - appendable.append('"').append(fd.getTagName()).append('"'); - appendable.append(':'); - appendable.append('['); - - } - - /** - * - * @param fd - * @param appendable - * @param close - * @throws IOException - */ - private void writeWrap(FieldDescriptor fd, Appendable appendable, boolean close) - throws IOException - { - if (fd.isWrapped()) - { - if (!close) - { - appendable.append('"'); - appendable.append(fd.getTagName()); - appendable.append('"').append(':'); - appendable.append('{'); - } - else - { - appendable.append('}'); - } - } - } - - /** - * - * @param object - * @param fd - * @param appendable - * @param translationContext - * @throws IOException - * @throws SIMPLTranslationException - */ - private void writeCollectionScalar(Object object, FieldDescriptor fd, Appendable appendable, - TranslationContext translationContext) throws IOException, SIMPLTranslationException - { - appendable.append('"'); - fd.appendCollectionScalarValue(appendable, object, translationContext, Format.JSON); - appendable.append('"'); - } - - /** - * - * @param fd - * @param appendable - * @param withTag - * @throws IOException - */ - private void writeObjectStart(FieldDescriptor fd, Appendable appendable, boolean withTag) - throws IOException - { - if (withTag) - { - appendable.append('"').append(fd.elementStart()).append('"'); - appendable.append(':'); - } - appendable.append('{'); - } - - /** - * - * @param object - * @param rootObjectFieldDescriptor - * @param appendable - * @throws IOException - */ - private void writeSimplRef(Object object, FieldDescriptor fd, boolean withTag, - Appendable appendable, TranslationContext translationContext) throws IOException - { - writeObjectStart(fd, appendable, withTag); - writeSimplRefAttribute(object, appendable, translationContext); - writeClose(appendable); - } - - private void writeSimplRefAttribute(Object object, Appendable appendable, TranslationContext translationContext) throws IOException - { - appendable.append('"'); - appendable.append(TranslationContext.JSON_SIMPL_REF); - appendable.append('"'); - appendable.append(':'); - appendable.append('"'); - appendable.append(translationContext.getSimplId(object)); - appendable.append('"'); - } - - private void writeSimplIdAttribute(Object object, Appendable appendable, boolean last) - throws IOException - { - appendable.append('"'); - appendable.append(TranslationContext.JSON_SIMPL_ID); - appendable.append('"'); - appendable.append(':'); - appendable.append('"'); - appendable.append(((Integer) object.hashCode()).toString()); - appendable.append('"'); - - if (!last) - { - appendable.append(','); - } - } - - /** - * - * @param appendable - * @throws IOException - */ - private void writeStart(Appendable appendable) throws IOException - { - appendable.append('{'); - } - - /** - * - * @param appendable - * @throws IOException - */ - private void writeClose(Appendable appendable) throws IOException - { - appendable.append('}'); - } -} +package ecologylab.serialization.serializers.stringformats; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.FieldTypes; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.FieldUsage; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.ScalarType; + +/*** + * JSONSerializaton. Guides serialization of data in JSON. Contains code that is specific to + * creating a valid JSON of the provided object. Supports graph handling. + * + * @author nabeel + * + */ +public class JSONSerializer extends StringSerializer implements FieldTypes +{ + private int numOfFields; + + public JSONSerializer() + { + + } + + @Override + public void serialize(Object object, Appendable appendable, TranslationContext translationContext) + throws SIMPLTranslationException + { + translationContext.resolveGraph(object); + + ClassDescriptor rootObjectClassDescriptor = ClassDescriptor + .getClassDescriptor(object.getClass()); + + try + { + writeStart(appendable); + + serialize(object, rootObjectClassDescriptor.pseudoFieldDescriptor(), appendable, + translationContext, true); + + writeClose(appendable); + } + catch (IOException e) + { + throw new SIMPLTranslationException("IO Exception occurred", e); + } + } + + /** + * + * @param object + * @param rootObjectFieldDescriptor + * @param appendable + * @param translationContext + * @param withTag + * @throws SIMPLTranslationException + * @throws IOException + */ + private void serialize(Object object, FieldDescriptor rootObjectFieldDescriptor, + Appendable appendable, TranslationContext translationContext, boolean withTag) + throws SIMPLTranslationException, IOException + { + if (alreadySerialized(object, translationContext)) + { + writeSimplRef(object, rootObjectFieldDescriptor, withTag, appendable, translationContext); + return; + } + + translationContext.mapObject(object); + + serializationPreHook(object, translationContext); + + writeObjectStart(rootObjectFieldDescriptor, appendable, withTag); + + //numOfFields = 0; + + ClassDescriptor classDescriptor = getClassDescriptor(object); + + serializeFields(object, appendable, translationContext, classDescriptor); + + writeClose(appendable); + + serializationPostHook(object, translationContext); + } + + /** + * + * @param object + * @param appendable + * @param translationContext + * @param allFieldDescriptors + * @throws SIMPLTranslationException + * @throws IOException + */ + private void serializeFields(Object object, Appendable appendable, + TranslationContext translationContext, + ClassDescriptor classDescriptor) throws SIMPLTranslationException, + IOException + { + ArrayList allFieldDescriptors = classDescriptor.allFieldDescriptors(); + + if (SimplTypesScope.graphSwitch == GRAPH_SWITCH.ON) + { + if (translationContext.needsHashCode(object)) + { + writeSimplIdAttribute(object, appendable, allFieldDescriptors.size() <= 0); + } + } + + ArrayList attributeFieldDescriptors = classDescriptor.attributeFieldDescriptors(); + int numOfFields = serializeFieldsHelper(appendable, object, translationContext, attributeFieldDescriptors, 0); + + if (classDescriptor.getScalarTextFD() != null){ + ArrayList textFieldDescriptors = new ArrayList(); + textFieldDescriptors.add(classDescriptor.getScalarTextFD()); + numOfFields += serializeFieldsHelper(appendable, object, translationContext, textFieldDescriptors, numOfFields); + } + + ArrayList elementFieldDescriptors = classDescriptor.elementFieldDescriptors(); + serializeFieldsHelper(appendable, object, translationContext, elementFieldDescriptors,numOfFields); + } + + private int serializeFieldsHelper(Appendable appendable, Object object, + TranslationContext translationContext, + ArrayList fieldDescriptorList, int numOfFields) throws SIMPLTranslationException, + IOException + { + + for (FieldDescriptor childFd : fieldDescriptorList) + { + if (isSerializable(childFd, object)) + { + if (numOfFields++ > 0) + appendable.append(','); + + switch (childFd.getType()) + { + case SCALAR: + serializeScalar(object, childFd, appendable, translationContext); + break; + case COMPOSITE_ELEMENT: + writeWrap(childFd, appendable, false); + serializeComposite(object, appendable, translationContext, childFd); + writeWrap(childFd, appendable, true); + break; + case COLLECTION_SCALAR: + case MAP_SCALAR: + serializeScalarCollection(object, appendable, translationContext, childFd); + break; + case COLLECTION_ELEMENT: + case MAP_ELEMENT: + if (childFd.isPolymorphic()) + serializePolymorphicCollection(object, appendable, translationContext, childFd); + else + serializeCompositeCollection(object, appendable, translationContext, childFd); + break; + } + } + } + return numOfFields; + } + + /** + * check if the field is of default value or null. we don't have to serialize that field + * + * @param childFd + * @param object + * @return + * @throws SIMPLTranslationException + */ + private boolean isSerializable(FieldDescriptor childFd, Object object) + throws SIMPLTranslationException + { + switch (childFd.getType()) + { + case SCALAR: + if (childFd.isDefaultValueFromContext(object)) + return false; + break; + case COMPOSITE_ELEMENT: + case COLLECTION_ELEMENT: + case MAP_ELEMENT: + Object obj = childFd.getValue(object); + if (obj == null) + return false; + break; + case COLLECTION_SCALAR: + case MAP_SCALAR: + Object scalarCollectionObject = childFd.getValue(object); + Collection scalarCollection = XMLTools.getCollection(scalarCollectionObject); + if (scalarCollection == null || scalarCollection.size() <= 0) + return false; + break; + } + + return true; + } + + /** + * + * @param object + * @param appendable + * @param translationContext + * @param childFd + * @throws SIMPLTranslationException + * @throws IOException + */ + private void serializeComposite(Object object, Appendable appendable, + TranslationContext translationContext, FieldDescriptor childFd) + throws SIMPLTranslationException, IOException + { + Object compositeObject = childFd.getValue(object); + FieldDescriptor compositeObjectFieldDescriptor = + childFd.isPolymorphic() + ? getClassDescriptor(compositeObject).pseudoFieldDescriptor() + : childFd; + serialize(compositeObject, compositeObjectFieldDescriptor, appendable, translationContext, true); + } + + /** + * + * @param object + * @param appendable + * @param translationContext + * @param childFd + * @throws IOException + * @throws SIMPLTranslationException + */ + private void serializeCompositeCollection(Object object, Appendable appendable, + TranslationContext translationContext, FieldDescriptor childFd) throws IOException, + SIMPLTranslationException + { + Object collectionObject = childFd.getValue(object); + Collection compositeCollection = XMLTools.getCollection(collectionObject); + + if(compositeCollection != null) + { + int numberOfItems = 0; + + writeCollectionStart(childFd, appendable); + for (Object collectionComposite : compositeCollection) + { + FieldDescriptor collectionObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( + collectionComposite).pseudoFieldDescriptor() + : childFd; + + serialize(collectionComposite, collectionObjectFieldDescriptor, appendable, + translationContext, false); + + if (++numberOfItems < compositeCollection.size()) + appendable.append(','); + } + writeCollectionEnd(appendable); + } + } + + /** + * + * @param object + * @param appendable + * @param translationContext + * @param childFd + * @throws IOException + * @throws SIMPLTranslationException + */ + private void serializePolymorphicCollection(Object object, Appendable appendable, + TranslationContext translationContext, FieldDescriptor childFd) throws IOException, + SIMPLTranslationException + { + Object collectionObject = childFd.getValue(object); + Collection compositeCollection = XMLTools.getCollection(collectionObject); + int numberOfItems = 0; + + if(compositeCollection != null) + { + writeCollectionStart(childFd, appendable); + for (Object collectionComposite : compositeCollection) + { + FieldDescriptor collectionObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( + collectionComposite).pseudoFieldDescriptor() + : childFd; + + writeStart(appendable); + serialize(collectionComposite, collectionObjectFieldDescriptor, appendable, + translationContext, true); + writeClose(appendable); + + if (++numberOfItems < compositeCollection.size()) + appendable.append(','); + } + writeCollectionEnd(appendable); + } + } + + /** + * + * @param object + * @param appendable + * @param translationContext + * @param childFd + * @throws IOException + * @throws SIMPLTranslationException + */ + private void serializeScalarCollection(Object object, Appendable appendable, + TranslationContext translationContext, FieldDescriptor childFd) throws IOException, + SIMPLTranslationException + { + Object scalarCollectionObject = childFd.getValue(object); + Collection scalarCollection = XMLTools.getCollection(scalarCollectionObject); + int numberOfItems = 0; + + if(scalarCollection != null) + { + writeCollectionStart(childFd, appendable); + for (Object collectionObject : scalarCollection) + { + writeCollectionScalar(collectionObject, childFd, appendable, translationContext); + if (++numberOfItems < scalarCollection.size()) + appendable.append(','); + } + writeCollectionEnd(appendable); + } + } + + /** + * + * @param object + * @param fd + * @param appendable + * @param translationContext + * @throws IOException + * @throws SIMPLTranslationException + */ + private void serializeScalar(Object object, FieldDescriptor fd, Appendable appendable, + TranslationContext translationContext) throws IOException, SIMPLTranslationException + { + // check wether we need quotation marks to surround the value. + boolean needQuotationMarks = true; + ScalarType st = fd.getScalarType(); + if (st != null){ + needQuotationMarks = st.needJsonSerializationQuotation(); + } + + appendable.append('"'); + appendable.append(fd.getTagName()); + appendable.append('"'); + appendable.append(':'); + if (needQuotationMarks) + appendable.append('"'); + fd.appendValue(appendable, object, translationContext, Format.JSON); + if (needQuotationMarks) + appendable.append('"'); + } + + /** + * + * @param appendable + * @throws IOException + */ + private void writeCollectionEnd(Appendable appendable) throws IOException + { + appendable.append(']'); + } + + private void writeCollectionStart(FieldDescriptor fd, Appendable appendable) throws IOException + { + appendable.append('"').append(fd.getTagName()).append('"'); + appendable.append(':'); + appendable.append('['); + } + + /** + * + * @param fd + * @param appendable + * @throws IOException + */ + private void writePolymorphicCollectionStart(FieldDescriptor fd, Appendable appendable) + throws IOException + { + appendable.append('"').append(fd.getTagName()).append('"'); + appendable.append(':'); + appendable.append('['); + + } + + /** + * + * @param fd + * @param appendable + * @param close + * @throws IOException + */ + private void writeWrap(FieldDescriptor fd, Appendable appendable, boolean close) + throws IOException + { + if (fd.isWrapped() || fd.isPolymorphic()) + { + if (!close) + { + appendable.append('"'); + appendable.append(fd.getTagName()); + appendable.append('"').append(':'); + appendable.append('{'); + } + else + { + appendable.append('}'); + } + } + } + + /** + * + * @param object + * @param fd + * @param appendable + * @param translationContext + * @throws IOException + * @throws SIMPLTranslationException + */ + private void writeCollectionScalar(Object object, FieldDescriptor fd, Appendable appendable, + TranslationContext translationContext) throws IOException, SIMPLTranslationException + { + appendable.append('"'); + fd.appendCollectionScalarValue(appendable, object, translationContext, Format.JSON); + appendable.append('"'); + } + + /** + * + * @param fd + * @param appendable + * @param withTag + * @throws IOException + */ + private void writeObjectStart(FieldDescriptor fd, Appendable appendable, boolean withTag) + throws IOException + { + if (withTag) + { + appendable.append('"').append(fd.elementStart()).append('"'); + appendable.append(':'); + } + appendable.append('{'); + } + + /** + * + * @param object + * @param rootObjectFieldDescriptor + * @param appendable + * @throws IOException + */ + private void writeSimplRef(Object object, FieldDescriptor fd, boolean withTag, + Appendable appendable, TranslationContext translationContext) throws IOException + { + writeObjectStart(fd, appendable, withTag); + writeSimplRefAttribute(object, appendable, translationContext); + writeClose(appendable); + } + + private void writeSimplRefAttribute(Object object, Appendable appendable, TranslationContext translationContext) throws IOException + { + appendable.append('"'); + appendable.append(TranslationContext.JSON_SIMPL_REF); + appendable.append('"'); + appendable.append(':'); + appendable.append('"'); + appendable.append(translationContext.getSimplId(object)); + appendable.append('"'); + } + + private void writeSimplIdAttribute(Object object, Appendable appendable, boolean last) + throws IOException + { + appendable.append('"'); + appendable.append(TranslationContext.JSON_SIMPL_ID); + appendable.append('"'); + appendable.append(':'); + appendable.append('"'); + appendable.append(((Integer) object.hashCode()).toString()); + appendable.append('"'); + + if (!last) + { + appendable.append(','); + } + } + + /** + * + * @param appendable + * @throws IOException + */ + private void writeStart(Appendable appendable) throws IOException + { + appendable.append('{'); + } + + /** + * + * @param appendable + * @throws IOException + */ + private void writeClose(Appendable appendable) throws IOException + { + appendable.append('}'); + } +} diff --git a/simplCore/src/ecologylab/serialization/serializers/stringformats/StringSerializer.java b/simplCore/src/ecologylab/serialization/serializers/stringformats/StringSerializer.java index eb728bcd..401a045f 100644 --- a/simplCore/src/ecologylab/serialization/serializers/stringformats/StringSerializer.java +++ b/simplCore/src/ecologylab/serialization/serializers/stringformats/StringSerializer.java @@ -1,123 +1,114 @@ -package ecologylab.serialization.serializers.stringformats; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.TranslationContextPool; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.serializers.FormatSerializer; - -public abstract class StringSerializer extends FormatSerializer -{ - - @Override - public void serialize(Object object, OutputStream outputStream, - TranslationContext translationContext) throws SIMPLTranslationException - { -// serialize(object, (Appendable) new PrintStream(outputStream), translationContext); - try - { - serialize(object, (Appendable) new PrintStream(outputStream, true, "utf-8"), translationContext); - } - catch (UnsupportedEncodingException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - @Override - public void serialize(Object object, File outputFile, TranslationContext translationContext) - throws SIMPLTranslationException - { - try - { - XMLTools.createParentDirs(outputFile); - - if (outputFile.getParentFile() != null) - translationContext.setBaseDirFile(outputFile.getParentFile()); - - BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(outputFile)); - serialize(object, bufferedWriter, translationContext); - - bufferedWriter.close(); - } - catch (IOException e) - { - throw new SIMPLTranslationException("IO Exception: ", e); - } - } - - /** - * - * @param object - * @return - * @throws SIMPLTranslationException - * @throws IOException - */ - public StringBuilder serialize(Object object) throws SIMPLTranslationException - { - TranslationContext translationContext = TranslationContextPool.get().acquire(); - StringBuilder sb = serialize(object, translationContext); - TranslationContextPool.get().release(translationContext); - return sb; - } - - /** - * - * @param object - * @param translationContext - * @return - * @throws SIMPLTranslationException - * @throws IOException - */ - public StringBuilder serialize(Object object, TranslationContext translationContext) - throws SIMPLTranslationException - { - final StringBuilder sb = new StringBuilder(); - serialize(object, sb, translationContext); - return sb; - } - - /** - * - * @param object - * @param stringBuilder - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - public void serialize(Object object, final StringBuilder stringBuilder, - TranslationContext translationContext) throws SIMPLTranslationException - { - OutputStream outputStream = new OutputStream() - { - @Override - public void write(int b) throws IOException - { - stringBuilder.append((char) b); - } - }; - - serialize(object, (Appendable) new PrintStream(outputStream), translationContext); - } - - /** - * All methods will eventually call this method which is overridden by derived classes - * - * @param object - * @param appendable - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - public abstract void serialize(Object object, Appendable appendable, - TranslationContext translationContext) throws SIMPLTranslationException; -} +package ecologylab.serialization.serializers.stringformats; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.TranslationContextPool; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.serializers.FormatSerializer; + +public abstract class StringSerializer extends FormatSerializer +{ + + @Override + public void serialize(Object object, OutputStream outputStream, + TranslationContext translationContext) throws SIMPLTranslationException + { +// serialize(object, (Appendable) new PrintStream(outputStream), translationContext); + try + { + serialize(object, (Appendable) new PrintStream(outputStream, true, "utf-8"), translationContext); + } + catch (UnsupportedEncodingException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Override + public void serialize(Object object, File outputFile, TranslationContext translationContext) + throws SIMPLTranslationException + { + try + { + XMLTools.createParentDirs(outputFile); + + if (outputFile.getParentFile() != null) + translationContext.setBaseDirFile(outputFile.getParentFile()); + + BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(outputFile)); + serialize(object, bufferedWriter, translationContext); + + bufferedWriter.close(); + } + catch (IOException e) + { + throw new SIMPLTranslationException("IO Exception: ", e); + } + } + + /** + * + * @param object + * @return + * @throws SIMPLTranslationException + * @throws IOException + */ + public StringBuilder serialize(Object object) throws SIMPLTranslationException + { + TranslationContext translationContext = TranslationContextPool.get().acquire(); + StringBuilder sb = serialize(object, translationContext); + TranslationContextPool.get().release(translationContext); + return sb; + } + + /** + * + * @param object + * @param translationContext + * @return + * @throws SIMPLTranslationException + * @throws IOException + */ + public StringBuilder serialize(Object object, TranslationContext translationContext) + throws SIMPLTranslationException + { + final StringBuilder sb = new StringBuilder(); + serialize(object, sb, translationContext); + return sb; + } + + /** + * + * @param object + * @param stringBuilder + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + public void serialize(Object object, final StringBuilder stringBuilder, + TranslationContext translationContext) throws SIMPLTranslationException + { + serialize(object, (Appendable) stringBuilder, translationContext); + } + + /** + * All methods will eventually call this method which is overridden by derived classes + * + * @param object + * @param appendable + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + public abstract void serialize(Object object, Appendable appendable, + TranslationContext translationContext) throws SIMPLTranslationException; +} diff --git a/simplCore/src/ecologylab/serialization/serializers/stringformats/XMLSerializer.java b/simplCore/src/ecologylab/serialization/serializers/stringformats/XMLSerializer.java index f80162db..e9186f57 100644 --- a/simplCore/src/ecologylab/serialization/serializers/stringformats/XMLSerializer.java +++ b/simplCore/src/ecologylab/serialization/serializers/stringformats/XMLSerializer.java @@ -1,435 +1,435 @@ -package ecologylab.serialization.serializers.stringformats; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.FieldTypes; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.annotations.FieldUsage; -import ecologylab.serialization.formatenums.Format; - -/** - * XML Specific serializer. contains functionalities specific to ouput syntax for XML from an objet - * model. - * - * @author nabeel - */ -public class XMLSerializer extends StringSerializer implements FieldTypes -{ - private static final String START_CDATA = ""; - - private boolean isRoot = true; - - public XMLSerializer() - { - } - - @Override - public void serialize(Object object, Appendable appendable, TranslationContext translationContext) - throws SIMPLTranslationException - { - translationContext.resolveGraph(object); - - ClassDescriptor rootObjectClassDescriptor = ClassDescriptor - .getClassDescriptor(object.getClass()); - - try - { - serialize(object, rootObjectClassDescriptor.pseudoFieldDescriptor(), appendable, - translationContext); - } - catch (IOException e) - { - throw new SIMPLTranslationException("IO Exception occurred", e); - } - } - - /** - * - * @param object - * @param rootObjectFieldDescriptor - * @param appendable - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - private void serialize(Object object, FieldDescriptor rootObjectFieldDescriptor, - Appendable appendable, TranslationContext translationContext) - throws SIMPLTranslationException, IOException - { - - if (object == null) - return; - - if (alreadySerialized(object, translationContext)) - { - writeSimplRef(object, rootObjectFieldDescriptor, appendable, translationContext); - return; - } - - translationContext.mapObject(object); - - serializationPreHook(object, translationContext); - - ClassDescriptor rootObjectClassDescriptor = getClassDescriptor(object); - - writeObjectStart(rootObjectFieldDescriptor, appendable); - - serializeAttributes(object, appendable, translationContext, rootObjectClassDescriptor); - - ArrayList elementFieldDescriptors = rootObjectClassDescriptor - .elementFieldDescriptors(); - - boolean hasXMLText = rootObjectClassDescriptor.hasScalarFD(); - boolean hasElements = elementFieldDescriptors.size() > 0; - - if (!hasElements && !hasXMLText) - { - // close tag no more elements - writeCompleteClose(appendable); - } - else - { - writeClose(appendable); - - if (hasXMLText) - { - writeValueAsText(object, rootObjectClassDescriptor.getScalarTextFD(), appendable); - } - - serializeFields(object, appendable, translationContext, elementFieldDescriptors); - - writeObjectClose(rootObjectFieldDescriptor, appendable); - } - - serializationPostHook(object, translationContext); - } - - /** - * - * @param object - * @param appendable - * @param translationContext - * @param rootObjectClassDescriptor - * @throws SIMPLTranslationException - * @throws IOException - */ - private void serializeAttributes(Object object, Appendable appendable, - TranslationContext translationContext, - ClassDescriptor rootObjectClassDescriptor) - throws SIMPLTranslationException, IOException - { - ArrayList attributeFieldDescriptors = rootObjectClassDescriptor - .attributeFieldDescriptors(); - - for (FieldDescriptor childFd : attributeFieldDescriptors) - { - try - { - writeValueAsAtrribute(object, childFd, appendable, translationContext); - } - catch (Exception ex) - { - throw new SIMPLTranslationException("serialize for attribute " + object, ex); - } - } - - if (SimplTypesScope.graphSwitch == GRAPH_SWITCH.ON) - { - if (translationContext.needsHashCode(object)) - { - writeSimplIdAttribute(object, appendable, translationContext); - } - - if (isRoot && translationContext.isGraph()) - { - writeSimplNameSpace(appendable); - isRoot = false; - } - } - } - - /** - * - * @param object - * @param appendable - * @param translationContext - * @param elementFieldDescriptors - * @throws SIMPLTranslationException - * @throws IOException - */ - private void serializeFields(Object object, Appendable appendable, - TranslationContext translationContext, - ArrayList elementFieldDescriptors) - throws SIMPLTranslationException, IOException - { - for (FieldDescriptor childFd : elementFieldDescriptors) - { - switch (childFd.getType()) - { - case SCALAR: - writeValueAsLeaf(object, childFd, appendable, translationContext); - break; - case COMPOSITE_ELEMENT: - Object compositeObject = childFd.getValue(object); - if (compositeObject != null) - { - FieldDescriptor compositeObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( - compositeObject).pseudoFieldDescriptor() - : childFd; - writeWrap(childFd, appendable, false); - serialize(compositeObject, compositeObjectFieldDescriptor, appendable, translationContext); - writeWrap(childFd, appendable, true); - } - break; - case COLLECTION_SCALAR: - case MAP_SCALAR: - Object scalarCollectionObject = childFd.getValue(object); - Collection scalarCollection = XMLTools.getCollection(scalarCollectionObject); - if (scalarCollection != null && scalarCollection.size() > 0) - { - writeWrap(childFd, appendable, false); - - for (Object collectionScalar : scalarCollection) - { - writeScalarCollectionLeaf(collectionScalar, childFd, appendable, translationContext); - } - writeWrap(childFd, appendable, true); - } - break; - case COLLECTION_ELEMENT: - case MAP_ELEMENT: - Object compositeCollectionObject = childFd.getValue(object); - Collection compositeCollection = XMLTools.getCollection(compositeCollectionObject); - if (compositeCollection != null && compositeCollection.size() > 0) - { - writeWrap(childFd, appendable, false); - for (Object collectionComposite : compositeCollection) - { - FieldDescriptor collectionObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( - collectionComposite).pseudoFieldDescriptor() - : childFd; - serialize(collectionComposite, collectionObjectFieldDescriptor, appendable, - translationContext); - } - writeWrap(childFd, appendable, true); - } - break; - } - } - } - - /** - * - * @param object - * @param fd - * @param appendable - * @throws IOException - */ - private void writeSimplRef(Object object, FieldDescriptor fd, Appendable appendable, TranslationContext translationContext) - throws IOException - { - writeObjectStart(fd, appendable); - writeSimplRefAttribute(object, appendable, translationContext); - writeCompleteClose(appendable); - } - - /** - * - * @param fd - * @param appendable - * @throws IOException - */ - private void writeObjectStart(FieldDescriptor fd, Appendable appendable) throws IOException - { - appendable.append('<').append(fd.elementStart()); - } - - /** - * - * @param fd - * @param appendable - * @throws IOException - */ - private void writeObjectClose(FieldDescriptor fd, Appendable appendable) throws IOException - { - appendable.append('<').append('/').append(fd.elementStart()).append('>'); - } - - /** - * - * @param appendable - * @throws IOException - */ - private void writeCompleteClose(Appendable appendable) throws IOException - { - appendable.append('/').append('>'); - } - - /** - * - * @param fd - * @param appendable - * @param close - * @throws IOException - */ - private void writeWrap(FieldDescriptor fd, Appendable appendable, boolean close) - throws IOException - { - if (fd.isWrapped()) - { - appendable.append('<'); - if (close) - appendable.append('/'); - appendable.append(fd.getTagName()).append('>'); - } - } - - /** - * - * @param object - * @param fd - * @param appendable - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - private void writeValueAsLeaf(Object object, FieldDescriptor fd, Appendable appendable, - TranslationContext translationContext) throws SIMPLTranslationException, IOException - { - if (!fd.isDefaultValueFromContext(object)) - { - appendable.append('<').append(fd.elementStart()).append('>'); - fd.appendValue(appendable, object, translationContext, Format.XML); - appendable.append('<').append('/').append(fd.elementStart()).append('>'); - } - } - - /** - * - * @param object - * @param fd - * @param appendable - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - private void writeScalarCollectionLeaf(Object object, FieldDescriptor fd, Appendable appendable, - TranslationContext translationContext) throws SIMPLTranslationException, IOException - { - appendable.append('<').append(fd.elementStart()).append('>'); - fd.appendCollectionScalarValue(appendable, object, translationContext, Format.XML); - appendable.append('<').append('/').append(fd.elementStart()).append('>'); - } - - /** - * - * @param object - * @param fd - * @param appendable - * @throws SIMPLTranslationException - * @throws IOException - */ - private void writeValueAsText(Object object, FieldDescriptor fd, Appendable appendable) - throws SIMPLTranslationException, IOException - { - if (!fd.isDefaultValueFromContext(object)) - { - if (fd.isCDATA()) - appendable.append(START_CDATA); - fd.appendValue(appendable, object, null, Format.XML); - if (fd.isCDATA()) - appendable.append(END_CDATA); - } - } - - /** - * - * @param appendable - * @throws IOException - */ - private void writeClose(Appendable appendable) throws IOException - { - appendable.append('>'); - } - - /** - * - * @param object - * @param fd - * @param appendable - * @param translationContext - * @throws SIMPLTranslationException - * @throws IOException - */ - private void writeValueAsAtrribute(Object object, FieldDescriptor fd, Appendable appendable, - TranslationContext translationContext) throws SIMPLTranslationException, IOException - { - if (object != null) - { - if (!fd.isDefaultValueFromContext(object)) - { - appendable.append(' '); - appendable.append(fd.getTagName()); - appendable.append('='); - appendable.append('"'); - - fd.appendValue(appendable, object, translationContext, Format.XML); - - appendable.append('"'); - } - } - } - - /** - * - * @param appendable - * @throws IOException - */ - private void writeSimplNameSpace(Appendable appendable) throws IOException - { - appendable.append(TranslationContext.SIMPL_NAMESPACE); - } - - /** - * - * @param object - * @param appendable - * @throws IOException - */ - private void writeSimplRefAttribute(Object object, Appendable appendable, TranslationContext translationContext) throws IOException - { - appendable.append(' '); - appendable.append(TranslationContext.SIMPL_REF); - appendable.append('='); - appendable.append('"'); - appendable.append(translationContext.getSimplId(object)); - appendable.append('"'); - } - - /** - * - * @param object - * @param appendable - * @throws IOException - */ - private void writeSimplIdAttribute(Object object, Appendable appendable, TranslationContext translationContext) throws IOException - { - appendable.append(' '); - appendable.append(TranslationContext.SIMPL_ID); - appendable.append('='); - appendable.append('"'); - appendable.append(translationContext.getSimplId(object)); - appendable.append('"'); - } - -} +package ecologylab.serialization.serializers.stringformats; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.FieldTypes; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.FieldUsage; +import ecologylab.serialization.formatenums.Format; + +/** + * XML Specific serializer. contains functionalities specific to ouput syntax for XML from an objet + * model. + * + * @author nabeel + */ +public class XMLSerializer extends StringSerializer implements FieldTypes +{ + private static final String START_CDATA = ""; + + private boolean isRoot = true; + + public XMLSerializer() + { + } + + @Override + public void serialize(Object object, Appendable appendable, TranslationContext translationContext) + throws SIMPLTranslationException + { + translationContext.resolveGraph(object); + + ClassDescriptor rootObjectClassDescriptor = ClassDescriptor + .getClassDescriptor(object.getClass()); + + try + { + serialize(object, rootObjectClassDescriptor.pseudoFieldDescriptor(), appendable, + translationContext); + } + catch (IOException e) + { + throw new SIMPLTranslationException("IO Exception occurred", e); + } + } + + /** + * + * @param object + * @param rootObjectFieldDescriptor + * @param appendable + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + private void serialize(Object object, FieldDescriptor rootObjectFieldDescriptor, + Appendable appendable, TranslationContext translationContext) + throws SIMPLTranslationException, IOException + { + + if (object == null) + return; + + if (alreadySerialized(object, translationContext)) + { + writeSimplRef(object, rootObjectFieldDescriptor, appendable, translationContext); + return; + } + + translationContext.mapObject(object); + + serializationPreHook(object, translationContext); + + ClassDescriptor rootObjectClassDescriptor = getClassDescriptor(object); + + writeObjectStart(rootObjectFieldDescriptor, appendable); + + serializeAttributes(object, appendable, translationContext, rootObjectClassDescriptor); + + ArrayList elementFieldDescriptors = rootObjectClassDescriptor + .elementFieldDescriptors(); + + boolean hasXMLText = rootObjectClassDescriptor.hasScalarFD(); + boolean hasElements = elementFieldDescriptors.size() > 0; + + if (!hasElements && !hasXMLText) + { + // close tag no more elements + writeCompleteClose(appendable); + } + else + { + writeClose(appendable); + + if (hasXMLText) + { + writeValueAsText(object, rootObjectClassDescriptor.getScalarTextFD(), appendable); + } + + serializeFields(object, appendable, translationContext, elementFieldDescriptors); + + writeObjectClose(rootObjectFieldDescriptor, appendable); + } + + serializationPostHook(object, translationContext); + } + + /** + * + * @param object + * @param appendable + * @param translationContext + * @param rootObjectClassDescriptor + * @throws SIMPLTranslationException + * @throws IOException + */ + private void serializeAttributes(Object object, Appendable appendable, + TranslationContext translationContext, + ClassDescriptor rootObjectClassDescriptor) + throws SIMPLTranslationException, IOException + { + ArrayList attributeFieldDescriptors = rootObjectClassDescriptor + .attributeFieldDescriptors(); + + for (FieldDescriptor childFd : attributeFieldDescriptors) + { + try + { + writeValueAsAtrribute(object, childFd, appendable, translationContext); + } + catch (Exception ex) + { + throw new SIMPLTranslationException("serialize for attribute " + object, ex); + } + } + + if (SimplTypesScope.graphSwitch == GRAPH_SWITCH.ON) + { + if (translationContext.needsHashCode(object)) + { + writeSimplIdAttribute(object, appendable, translationContext); + } + + if (isRoot && translationContext.isGraph()) + { + writeSimplNameSpace(appendable); + isRoot = false; + } + } + } + + /** + * + * @param object + * @param appendable + * @param translationContext + * @param elementFieldDescriptors + * @throws SIMPLTranslationException + * @throws IOException + */ + private void serializeFields(Object object, Appendable appendable, + TranslationContext translationContext, + ArrayList elementFieldDescriptors) + throws SIMPLTranslationException, IOException + { + for (FieldDescriptor childFd : elementFieldDescriptors) + { + switch (childFd.getType()) + { + case SCALAR: + writeValueAsLeaf(object, childFd, appendable, translationContext); + break; + case COMPOSITE_ELEMENT: + Object compositeObject = childFd.getValue(object); + if (compositeObject != null) + { + FieldDescriptor compositeObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( + compositeObject).pseudoFieldDescriptor() + : childFd; + writeWrap(childFd, appendable, false); + serialize(compositeObject, compositeObjectFieldDescriptor, appendable, translationContext); + writeWrap(childFd, appendable, true); + } + break; + case COLLECTION_SCALAR: + case MAP_SCALAR: + Object scalarCollectionObject = childFd.getValue(object); + Collection scalarCollection = XMLTools.getCollection(scalarCollectionObject); + if (scalarCollection != null && scalarCollection.size() > 0) + { + writeWrap(childFd, appendable, false); + + for (Object collectionScalar : scalarCollection) + { + writeScalarCollectionLeaf(collectionScalar, childFd, appendable, translationContext); + } + writeWrap(childFd, appendable, true); + } + break; + case COLLECTION_ELEMENT: + case MAP_ELEMENT: + Object compositeCollectionObject = childFd.getValue(object); + Collection compositeCollection = XMLTools.getCollection(compositeCollectionObject); + if (compositeCollection != null && compositeCollection.size() > 0) + { + writeWrap(childFd, appendable, false); + for (Object collectionComposite : compositeCollection) + { + FieldDescriptor collectionObjectFieldDescriptor = childFd.isPolymorphic() ? getClassDescriptor( + collectionComposite).pseudoFieldDescriptor() + : childFd; + serialize(collectionComposite, collectionObjectFieldDescriptor, appendable, + translationContext); + } + writeWrap(childFd, appendable, true); + } + break; + } + } + } + + /** + * + * @param object + * @param fd + * @param appendable + * @throws IOException + */ + private void writeSimplRef(Object object, FieldDescriptor fd, Appendable appendable, TranslationContext translationContext) + throws IOException + { + writeObjectStart(fd, appendable); + writeSimplRefAttribute(object, appendable, translationContext); + writeCompleteClose(appendable); + } + + /** + * + * @param fd + * @param appendable + * @throws IOException + */ + private void writeObjectStart(FieldDescriptor fd, Appendable appendable) throws IOException + { + appendable.append('<').append(fd.elementStart()); + } + + /** + * + * @param fd + * @param appendable + * @throws IOException + */ + private void writeObjectClose(FieldDescriptor fd, Appendable appendable) throws IOException + { + appendable.append('<').append('/').append(fd.elementStart()).append('>'); + } + + /** + * + * @param appendable + * @throws IOException + */ + private void writeCompleteClose(Appendable appendable) throws IOException + { + appendable.append('/').append('>'); + } + + /** + * + * @param fd + * @param appendable + * @param close + * @throws IOException + */ + private void writeWrap(FieldDescriptor fd, Appendable appendable, boolean close) + throws IOException + { + if (fd.isWrapped()) + { + appendable.append('<'); + if (close) + appendable.append('/'); + appendable.append(fd.getTagName()).append('>'); + } + } + + /** + * + * @param object + * @param fd + * @param appendable + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + private void writeValueAsLeaf(Object object, FieldDescriptor fd, Appendable appendable, + TranslationContext translationContext) throws SIMPLTranslationException, IOException + { + if (!fd.isDefaultValueFromContext(object)) + { + appendable.append('<').append(fd.elementStart()).append('>'); + fd.appendValue(appendable, object, translationContext, Format.XML); + appendable.append('<').append('/').append(fd.elementStart()).append('>'); + } + } + + /** + * + * @param object + * @param fd + * @param appendable + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + private void writeScalarCollectionLeaf(Object object, FieldDescriptor fd, Appendable appendable, + TranslationContext translationContext) throws SIMPLTranslationException, IOException + { + appendable.append('<').append(fd.elementStart()).append('>'); + fd.appendCollectionScalarValue(appendable, object, translationContext, Format.XML); + appendable.append('<').append('/').append(fd.elementStart()).append('>'); + } + + /** + * + * @param object + * @param fd + * @param appendable + * @throws SIMPLTranslationException + * @throws IOException + */ + private void writeValueAsText(Object object, FieldDescriptor fd, Appendable appendable) + throws SIMPLTranslationException, IOException + { + if (!fd.isDefaultValueFromContext(object)) + { + if (fd.isCDATA()) + appendable.append(START_CDATA); + fd.appendValue(appendable, object, null, Format.XML); + if (fd.isCDATA()) + appendable.append(END_CDATA); + } + } + + /** + * + * @param appendable + * @throws IOException + */ + private void writeClose(Appendable appendable) throws IOException + { + appendable.append('>'); + } + + /** + * + * @param object + * @param fd + * @param appendable + * @param translationContext + * @throws SIMPLTranslationException + * @throws IOException + */ + private void writeValueAsAtrribute(Object object, FieldDescriptor fd, Appendable appendable, + TranslationContext translationContext) throws SIMPLTranslationException, IOException + { + if (object != null) + { + if (!fd.isDefaultValueFromContext(object)) + { + appendable.append(' '); + appendable.append(fd.getTagName()); + appendable.append('='); + appendable.append('"'); + + fd.appendValue(appendable, object, translationContext, Format.XML); + + appendable.append('"'); + } + } + } + + /** + * + * @param appendable + * @throws IOException + */ + private void writeSimplNameSpace(Appendable appendable) throws IOException + { + appendable.append(TranslationContext.SIMPL_NAMESPACE); + } + + /** + * + * @param object + * @param appendable + * @throws IOException + */ + private void writeSimplRefAttribute(Object object, Appendable appendable, TranslationContext translationContext) throws IOException + { + appendable.append(' '); + appendable.append(TranslationContext.SIMPL_REF); + appendable.append('='); + appendable.append('"'); + appendable.append(translationContext.getSimplId(object)); + appendable.append('"'); + } + + /** + * + * @param object + * @param appendable + * @throws IOException + */ + private void writeSimplIdAttribute(Object object, Appendable appendable, TranslationContext translationContext) throws IOException + { + appendable.append(' '); + appendable.append(TranslationContext.SIMPL_ID); + appendable.append('='); + appendable.append('"'); + appendable.append(translationContext.getSimplId(object)); + appendable.append('"'); + } + +} diff --git a/simplCore/src/ecologylab/serialization/simplstringformats/FormatRegistry.java b/simplCore/src/ecologylab/serialization/simplstringformats/FormatRegistry.java index 616f0b40..7a5d4b23 100644 --- a/simplCore/src/ecologylab/serialization/simplstringformats/FormatRegistry.java +++ b/simplCore/src/ecologylab/serialization/simplstringformats/FormatRegistry.java @@ -1,39 +1,39 @@ -package ecologylab.serialization.simplstringformats; - -import java.util.HashMap; -import java.util.Map; - -import ecologylab.serialization.ISimplStringFormat; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -public class FormatRegistry { - - - private static Map formats; - - private static Map standardFormats; - - // TODO: STructure this more like type registry / simpl type scope... - // TODO: Avoid use of enums for extensibility in the future. Possibly leverage multiscope idea (to be implemented) - static - { - formats = new HashMap(); - formats.put(StringFormat.XML, new XMLFormat()); - formats.put(StringFormat.JSON, new JSONFormat()); - - standardFormats = new HashMap(); - standardFormats.put(Format.XML, new XMLFormat()); - standardFormats.put(Format.JSON, new JSONFormat()); - } - - public static ISimplStringFormat get(StringFormat sf) - { - return formats.get(sf); - } - - public static ISimplStringFormat get(Format f) - { - return standardFormats.get(f); - } -} +package ecologylab.serialization.simplstringformats; + +import java.util.HashMap; +import java.util.Map; + +import ecologylab.serialization.ISimplStringFormat; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +public class FormatRegistry { + + + private static Map formats; + + private static Map standardFormats; + + // TODO: STructure this more like type registry / simpl type scope... + // TODO: Avoid use of enums for extensibility in the future. Possibly leverage multiscope idea (to be implemented) + static + { + formats = new HashMap(); + formats.put(StringFormat.XML, new XMLFormat()); + formats.put(StringFormat.JSON, new JSONFormat()); + + standardFormats = new HashMap(); + standardFormats.put(Format.XML, new XMLFormat()); + standardFormats.put(Format.JSON, new JSONFormat()); + } + + public static ISimplStringFormat get(StringFormat sf) + { + return formats.get(sf); + } + + public static ISimplStringFormat get(Format f) + { + return standardFormats.get(f); + } +} diff --git a/simplCore/src/ecologylab/serialization/simplstringformats/JSONFormat.java b/simplCore/src/ecologylab/serialization/simplstringformats/JSONFormat.java index 14f53cce..d99b7ba3 100644 --- a/simplCore/src/ecologylab/serialization/simplstringformats/JSONFormat.java +++ b/simplCore/src/ecologylab/serialization/simplstringformats/JSONFormat.java @@ -1,42 +1,42 @@ -package ecologylab.serialization.simplstringformats; - -import org.json.simple.JSONValue; - -import ecologylab.serialization.ISimplStringFormat; - -// TODO: MAY need to move to platform specifics. :\ -public class JSONFormat implements ISimplStringFormat{ - - @Override - public String escape(String unescapedString) { - if(unescapedString == null) - { - return ""; - } - - // TODO: CONSIDER CHANGING THIS TO ANOTHER LIBRARY? - return JSONValue.escape(unescapedString); // This is what the String scalar type does to escape. - // Not sure if this is sufficient,b ut we've been relying on it thus far at least for strings. - } - - @Override - public String unescape(String escapedString) { - if(escapedString == null) - { - return ""; - } - - try - { - // We add the "'s to make it parse-able as a string. - // This could be improved, works for now. - Object o = JSONValue.parseWithException("\""+escapedString+"\""); - return o.toString(); - } - catch(Exception e) - { - throw new RuntimeException("Couldn't unescape the string:" + escapedString); - } - } - -} +package ecologylab.serialization.simplstringformats; + +import org.json.simple.JSONValue; + +import ecologylab.serialization.ISimplStringFormat; + +// TODO: MAY need to move to platform specifics. :\ +public class JSONFormat implements ISimplStringFormat{ + + @Override + public String escape(String unescapedString) { + if(unescapedString == null) + { + return ""; + } + + // TODO: CONSIDER CHANGING THIS TO ANOTHER LIBRARY? + return JSONValue.escape(unescapedString); // This is what the String scalar type does to escape. + // Not sure if this is sufficient,b ut we've been relying on it thus far at least for strings. + } + + @Override + public String unescape(String escapedString) { + if(escapedString == null) + { + return ""; + } + + try + { + // We add the "'s to make it parse-able as a string. + // This could be improved, works for now. + Object o = JSONValue.parseWithException("\""+escapedString+"\""); + return o.toString(); + } + catch(Exception e) + { + throw new RuntimeException("Couldn't unescape the string:" + escapedString); + } + } + +} diff --git a/simplCore/src/ecologylab/serialization/simplstringformats/XMLFormat.java b/simplCore/src/ecologylab/serialization/simplstringformats/XMLFormat.java index f349ab06..cb3bf4a1 100644 --- a/simplCore/src/ecologylab/serialization/simplstringformats/XMLFormat.java +++ b/simplCore/src/ecologylab/serialization/simplstringformats/XMLFormat.java @@ -1,22 +1,22 @@ -package ecologylab.serialization.simplstringformats; - -import ecologylab.serialization.ISimplStringFormat; -import ecologylab.serialization.XMLTools; - -// TODO: May need to move to Platform Specifics in the future. -public class XMLFormat implements ISimplStringFormat{ - - @Override - public String escape(String unescapedString) { - // TODO: Replace with a standard library for escaping XML - StringBuilder ourStringBuilder = new StringBuilder(); - XMLTools.escapeXML(ourStringBuilder, unescapedString); // TODO: Change this interface. My god that's terrible. - return ourStringBuilder.toString(); - } - - @Override - public String unescape(String escapedString) { - //TODO: Replace with a standard library for escaping XML - return XMLTools.unescapeXML(escapedString); - } -} +package ecologylab.serialization.simplstringformats; + +import ecologylab.serialization.ISimplStringFormat; +import ecologylab.serialization.XMLTools; + +// TODO: May need to move to Platform Specifics in the future. +public class XMLFormat implements ISimplStringFormat{ + + @Override + public String escape(String unescapedString) { + // TODO: Replace with a standard library for escaping XML + StringBuilder ourStringBuilder = new StringBuilder(); + XMLTools.escapeXML(ourStringBuilder, unescapedString); // TODO: Change this interface. My god that's terrible. + return ourStringBuilder.toString(); + } + + @Override + public String unescape(String escapedString) { + //TODO: Replace with a standard library for escaping XML + return XMLTools.unescapeXML(escapedString); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/CollectionType.java b/simplCore/src/ecologylab/serialization/types/CollectionType.java index ed3d7ae8..81ecdf2d 100644 --- a/simplCore/src/ecologylab/serialization/types/CollectionType.java +++ b/simplCore/src/ecologylab/serialization/types/CollectionType.java @@ -1,91 +1,91 @@ -/** - * - */ -package ecologylab.serialization.types; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - -import ecologylab.serialization.GenericTypeVar; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * Basic cross-platform unit for managing Collection and Map types in S.IM.PL Serialization. - * - * @author andruid - */ -@simpl_inherit -public class CollectionType extends SimplType -implements CrossLanguageTypeConstants -{ - @simpl_scalar - private boolean isMap; - - /** - * Represent the generic type vars that a Collection or Map type is defined with. - */ - @simpl_collection("generic_type_var") - private ArrayList genericTypeVars; - - /** - * Default constructor to satisfy SIMPL - */ - public CollectionType() - { - } - - public CollectionType(Class javaClass, String cSharpName, String objCName) - { - super(javaClass, false, cSharpName, objCName, null); - - this.isMap = Map.class.isAssignableFrom(javaClass); - } - - public Collection getCollection() - { - return isMap ? null : (Collection) getInstance(); - } - - public Map getMap() - { - return isMap ? (Map) getInstance() : null; - } - - public boolean isMap() - { - return isMap; - } - - /** - * The name to use when declaring a field in C# cross-compilation. - * - * @return cSharpTypeName, if one was passed in explicitly. otherwise, the cSharpTypeName of the default Collection or Map type. - */ - @Override - public String deriveCSharpTypeName() - { - String cSharpTypeName = super.getCSharpTypeName(); - return cSharpTypeName != null ? cSharpTypeName : TypeRegistry.getDefaultCollectionOrMapType(isMap).getCSharpTypeName(); - } - - /** - * The name to use when declaring a field in Objective C cross-compilation. - * - * @return objectiveCTypeName, if one was passed in explicitly. otherwise, the objectiveCTypeName of the default Collection or Map type. - */ - @Override - public String deriveObjectiveCTypeName() - { - String objectiveCTypeName = super.getObjectiveCTypeName(); - return objectiveCTypeName != null ? objectiveCTypeName : TypeRegistry.getDefaultCollectionOrMapType(isMap).getObjectiveCTypeName(); - } - - @Override - public boolean isScalar() - { - return false; - } -} +/** + * + */ +package ecologylab.serialization.types; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +import ecologylab.serialization.GenericTypeVar; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Basic cross-platform unit for managing Collection and Map types in S.IM.PL Serialization. + * + * @author andruid + */ +@simpl_inherit +public class CollectionType extends SimplType +implements CrossLanguageTypeConstants +{ + @simpl_scalar + private boolean isMap; + + /** + * Represent the generic type vars that a Collection or Map type is defined with. + */ + @simpl_collection("generic_type_var") + private ArrayList genericTypeVars; + + /** + * Default constructor to satisfy SIMPL + */ + public CollectionType() + { + } + + public CollectionType(Class javaClass, String cSharpName, String objCName) + { + super(javaClass, false, cSharpName, objCName, null); + + this.isMap = Map.class.isAssignableFrom(javaClass); + } + + public Collection getCollection() + { + return isMap ? null : (Collection) getInstance(); + } + + public Map getMap() + { + return isMap ? (Map) getInstance() : null; + } + + public boolean isMap() + { + return isMap; + } + + /** + * The name to use when declaring a field in C# cross-compilation. + * + * @return cSharpTypeName, if one was passed in explicitly. otherwise, the cSharpTypeName of the default Collection or Map type. + */ + @Override + public String deriveCSharpTypeName() + { + String cSharpTypeName = super.getCSharpTypeName(); + return cSharpTypeName != null ? cSharpTypeName : TypeRegistry.getDefaultCollectionOrMapType(isMap).getCSharpTypeName(); + } + + /** + * The name to use when declaring a field in Objective C cross-compilation. + * + * @return objectiveCTypeName, if one was passed in explicitly. otherwise, the objectiveCTypeName of the default Collection or Map type. + */ + @Override + public String deriveObjectiveCTypeName() + { + String objectiveCTypeName = super.getObjectiveCTypeName(); + return objectiveCTypeName != null ? objectiveCTypeName : TypeRegistry.getDefaultCollectionOrMapType(isMap).getObjectiveCTypeName(); + } + + @Override + public boolean isScalar() + { + return false; + } +} diff --git a/simplCore/src/ecologylab/serialization/types/CrossLanguageTypeConstants.java b/simplCore/src/ecologylab/serialization/types/CrossLanguageTypeConstants.java index e4077b27..5e837428 100644 --- a/simplCore/src/ecologylab/serialization/types/CrossLanguageTypeConstants.java +++ b/simplCore/src/ecologylab/serialization/types/CrossLanguageTypeConstants.java @@ -1,180 +1,180 @@ -package ecologylab.serialization.types; - -/** - * Type constants for defining many SimplTypes across Java, C#, and Objective C. - * - * @author andruid - */ -public interface CrossLanguageTypeConstants -{ - /** - * Prefix for unique S.IM.PL Collection Type Names - */ - public static final String SIMPL_COLLECTION_TYPES_PREFIX = "simpl.types.collection."; - - /** - * Prefix for unique S.IM.PL Scalar Type Names - */ - public static final String SIMPL_SCALAR_TYPES_PREFIX = "simpl.types.scalar."; - - - /* - * Objective-C Scalar types - */ - public static final String OBJC_INTEGER = "int"; - - public static final String OBJC_FLOAT = "float"; - - public static final String OBJC_DOUBLE = "double"; - - public static final String OBJC_BYTE = "char"; - - public static final String OBJC_CHAR = "char"; - - public static final String OBJC_BOOLEAN = "bool"; - - public static final String OBJC_LONG = "long"; - - public static final String OBJC_SHORT = "short"; - - public static final String OBJC_STRING = "NSString"; - - public static final String OBJC_OBJECT = "NSObject"; - - public static final String OBJC_DATE = "NSDate"; - - public static final String OBJC_STRING_BUILDER = "NSMutableString"; - - public static final String OBJC_URL = "NSURL"; - - public static final String OBJC_PARSED_URL = "ParsedURL"; - - public static final String OBJC_SCALAR_TYPE = "NSScalarType"; - - public static final String OBJC_CLASS = "Class"; - - public static final String OBJC_FIELD = "Ivar"; - - public static final String OBJC_COLOR = "UIColor"; - - public static final String OBJC_FILE = "NSFileHandle"; - - public static final String OBJC_ARRAYLIST = "NSMutableArray"; - - public static final String OBJC_HASHMAP = "NSDictionary"; - - public static final String OBJC_HASHMAPARRAYLIST = "NSDictionaryList"; - - public static final String OBJC_SCOPE = "NSScope"; - - public static final String OBJC_PATTERN = "NSRegularExpression"; - - /* - * C Sharp Scalar Types - */ - public static final String DOTNET_INTEGER = "Int32"; - - public static final String DOTNET_FLOAT = "Single"; - - public static final String DOTNET_DOUBLE = "Double"; - - public static final String DOTNET_BYTE = "Char"; - - public static final String DOTNET_CHAR = "Byte"; - - public static final String DOTNET_BOOLEAN = "Boolean"; - - public static final String DOTNET_LONG = "Int64"; - - public static final String DOTNET_SHORT = "Int16"; - - public static final String DOTNET_STRING = "String"; - - public static final String DOTNET_DATE = "DateTime"; - - public static final String DOTNET_STRING_BUILDER = "System.Text.StringBuilder"; - - public static final String DOTNET_URL = "Uri"; - - public static final String DOTNET_PARSED_URL = "Simpl.Fundamental.Net.ParsedUri"; - - public static final String DOTNET_SCALAR_TYPE = "Simpl.Serialization.Types.ScalarType"; - - public static final String DOTNET_CLASS = "Type"; - - public static final String DOTNET_FIELD = "System.Reflection.FieldInfo"; - - public static final String DOTNET_COLOR = "Color"; // namespace? - - public static final String DOTNET_FILE = "System.IO.FileInfo"; - - public static final String DOTNET_ARRAYLIST = "List"; // System.Collections.Generic - - public static final String DOTNET_HASHMAP = "Dictionary"; // System.Collections.Generic - - public static final String DOTNET_HASHMAPARRAYLIST = "DictionaryList"; // Simpl.Fundamental.Generic - - public static final String DOTNET_SCOPE = "Scope"; // ecologylab.collections - - public static final String DOTNET_UUID = "Guid"; - - public static final String DOTNET_PATTERN = "System.Text.RegularExpressions.Regex"; - - public static final String DOTNET_BINARY_DATA = "MemoryStream"; - - /* - * Java Scalar Types - */ - public static final String JAVA_INTEGER = "int"; - - public static final String JAVA_FLOAT = "float"; - - public static final String JAVA_DOUBLE = "double"; - - public static final String JAVA_BYTE = "byte"; - - public static final String JAVA_CHAR = "char"; - - public static final String JAVA_BOOLEAN = "boolean"; - - public static final String JAVA_LONG = "long"; - - public static final String JAVA_SHORT = "short"; - - public static final String JAVA_STRING = "String"; - - public static final String JAVA_DATE = "Date"; - - public static final String JAVA_STRING_BUILDER = "StringBuilder"; - - public static final String JAVA_URL = "Url"; - - public static final String JAVA_PARSED_URL = "ParsedURL"; - - public static final String JAVA_SCALAR_TYPE = "ScalarType"; - - public static final String JAVA_CLASS = "Class"; - - public static final String JAVA_FIELD = "Field"; - - public static final String JAVA_COLOR = "Color"; - - public static final String JAVA_FILE = "File"; - - public static final String JAVA_ARRAYLIST = "ArrayList"; - - public static final String JAVA_HASHMAP = "HashMap"; - - public static final String JAVA_HASHMAPARRAYLIST = "HashMapArrayList"; - - public static final String JAVA_SCOPE = "Scope"; - - public static final String JAVA_UUID = "GUID"; - - public static final String JAVA_RECTANGLE = "Rectangle"; - - public static final String JAVA_PATTERN = "Pattern"; - - public static final String JAVA_BINARY_DATA = "ByteBuffer"; - -} +package ecologylab.serialization.types; + +/** + * Type constants for defining many SimplTypes across Java, C#, and Objective C. + * + * @author andruid + */ +public interface CrossLanguageTypeConstants +{ + /** + * Prefix for unique S.IM.PL Collection Type Names + */ + public static final String SIMPL_COLLECTION_TYPES_PREFIX = "simpl.types.collection."; + + /** + * Prefix for unique S.IM.PL Scalar Type Names + */ + public static final String SIMPL_SCALAR_TYPES_PREFIX = "simpl.types.scalar."; + + + /* + * Objective-C Scalar types + */ + public static final String OBJC_INTEGER = "int"; + + public static final String OBJC_FLOAT = "float"; + + public static final String OBJC_DOUBLE = "double"; + + public static final String OBJC_BYTE = "char"; + + public static final String OBJC_CHAR = "char"; + + public static final String OBJC_BOOLEAN = "bool"; + + public static final String OBJC_LONG = "long"; + + public static final String OBJC_SHORT = "short"; + + public static final String OBJC_STRING = "NSString"; + + public static final String OBJC_OBJECT = "NSObject"; + + public static final String OBJC_DATE = "NSDate"; + + public static final String OBJC_STRING_BUILDER = "NSMutableString"; + + public static final String OBJC_URL = "NSURL"; + + public static final String OBJC_PARSED_URL = "ParsedURL"; + + public static final String OBJC_SCALAR_TYPE = "NSScalarType"; + + public static final String OBJC_CLASS = "Class"; + + public static final String OBJC_FIELD = "Ivar"; + + public static final String OBJC_COLOR = "UIColor"; + + public static final String OBJC_FILE = "NSFileHandle"; + + public static final String OBJC_ARRAYLIST = "NSMutableArray"; + + public static final String OBJC_HASHMAP = "NSDictionary"; + + public static final String OBJC_HASHMAPARRAYLIST = "NSDictionaryList"; + + public static final String OBJC_SCOPE = "NSScope"; + + public static final String OBJC_PATTERN = "NSRegularExpression"; + + /* + * C Sharp Scalar Types + */ + public static final String DOTNET_INTEGER = "Int32"; + + public static final String DOTNET_FLOAT = "Single"; + + public static final String DOTNET_DOUBLE = "Double"; + + public static final String DOTNET_BYTE = "Char"; + + public static final String DOTNET_CHAR = "Byte"; + + public static final String DOTNET_BOOLEAN = "Boolean"; + + public static final String DOTNET_LONG = "Int64"; + + public static final String DOTNET_SHORT = "Int16"; + + public static final String DOTNET_STRING = "String"; + + public static final String DOTNET_DATE = "DateTime"; + + public static final String DOTNET_STRING_BUILDER = "System.Text.StringBuilder"; + + public static final String DOTNET_URL = "Uri"; + + public static final String DOTNET_PARSED_URL = "Simpl.Fundamental.Net.ParsedUri"; + + public static final String DOTNET_SCALAR_TYPE = "Simpl.Serialization.Types.ScalarType"; + + public static final String DOTNET_CLASS = "Type"; + + public static final String DOTNET_FIELD = "System.Reflection.FieldInfo"; + + public static final String DOTNET_COLOR = "Color"; // namespace? + + public static final String DOTNET_FILE = "System.IO.FileInfo"; + + public static final String DOTNET_ARRAYLIST = "List"; // System.Collections.Generic + + public static final String DOTNET_HASHMAP = "Dictionary"; // System.Collections.Generic + + public static final String DOTNET_HASHMAPARRAYLIST = "DictionaryList"; // Simpl.Fundamental.Generic + + public static final String DOTNET_SCOPE = "Scope"; // ecologylab.collections + + public static final String DOTNET_UUID = "Guid"; + + public static final String DOTNET_PATTERN = "System.Text.RegularExpressions.Regex"; + + public static final String DOTNET_BINARY_DATA = "MemoryStream"; + + /* + * Java Scalar Types + */ + public static final String JAVA_INTEGER = "int"; + + public static final String JAVA_FLOAT = "float"; + + public static final String JAVA_DOUBLE = "double"; + + public static final String JAVA_BYTE = "byte"; + + public static final String JAVA_CHAR = "char"; + + public static final String JAVA_BOOLEAN = "boolean"; + + public static final String JAVA_LONG = "long"; + + public static final String JAVA_SHORT = "short"; + + public static final String JAVA_STRING = "String"; + + public static final String JAVA_DATE = "Date"; + + public static final String JAVA_STRING_BUILDER = "StringBuilder"; + + public static final String JAVA_URL = "Url"; + + public static final String JAVA_PARSED_URL = "ParsedURL"; + + public static final String JAVA_SCALAR_TYPE = "ScalarType"; + + public static final String JAVA_CLASS = "Class"; + + public static final String JAVA_FIELD = "Field"; + + public static final String JAVA_COLOR = "Color"; + + public static final String JAVA_FILE = "File"; + + public static final String JAVA_ARRAYLIST = "ArrayList"; + + public static final String JAVA_HASHMAP = "HashMap"; + + public static final String JAVA_HASHMAPARRAYLIST = "HashMapArrayList"; + + public static final String JAVA_SCOPE = "Scope"; + + public static final String JAVA_UUID = "GUID"; + + public static final String JAVA_RECTANGLE = "Rectangle"; + + public static final String JAVA_PATTERN = "Pattern"; + + public static final String JAVA_BINARY_DATA = "ByteBuffer"; + +} diff --git a/simplCore/src/ecologylab/serialization/types/FundamentalTypes.java b/simplCore/src/ecologylab/serialization/types/FundamentalTypes.java index 8d4dcbec..20a80207 100644 --- a/simplCore/src/ecologylab/serialization/types/FundamentalTypes.java +++ b/simplCore/src/ecologylab/serialization/types/FundamentalTypes.java @@ -1,101 +1,101 @@ -package ecologylab.serialization.types; - -import java.io.File; -import java.lang.reflect.Field; -import java.net.URL; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.UUID; -import java.util.regex.Pattern; - -import ecologylab.collections.Scope; -import ecologylab.generic.HashMapArrayList; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.types.scalar.*; - -public class FundamentalTypes -implements CrossLanguageTypeConstants -{ - public static final CollectionType ARRAYLIST_TYPE = - new CollectionType(ArrayList.class, DOTNET_ARRAYLIST, OBJC_ARRAYLIST); - - public static final CollectionType HASHMAP_TYPE = - new CollectionType(HashMap.class, DOTNET_HASHMAP, OBJC_HASHMAP); - - public static final CollectionType HASHMAPARRAYLIST_TYPE = - new CollectionType( HashMapArrayList.class, DOTNET_HASHMAPARRAYLIST, OBJC_HASHMAPARRAYLIST); - - public static final CollectionType SCOPE_TYPE = - new CollectionType(Scope.class, DOTNET_SCOPE, OBJC_SCOPE); - - static - { - TypeRegistry.setDefaultCollectionType(ARRAYLIST_TYPE); - TypeRegistry.setDefaultMapType(HASHMAP_TYPE); - } - - public static final ScalarType STRING_TYPE = new StringType(); - - public static final ScalarType STRING_BUILDER_TYPE = new StringBuilderType(); - - public static final ScalarType INT_TYPE = new IntType(); - - public static final ScalarType REFERENCE_INTEGER_TYPE = new ReferenceIntegerType(); - - public static final ScalarType LONG_TYPE = new LongType(); - - public static final ScalarType REFERENCE_LONG_TYPE = new ReferenceLongType(); - - public static final ScalarType BOOLEAN_TYPE = new BooleanType(); - - public static final ScalarType REFERENCE_BOOLEAN_TYPE = new ReferenceBooleanType(); - - public static final ScalarType FLOAT_TYPE = new FloatType(); - - public static final ScalarType REFERENCE_FLOAT_TYPE = new ReferenceFloatType(); - - public static final ScalarType DOUBLE_TYPE = new DoubleType(); - - public static final ScalarType REFERENCE_DOUBLE_TYPE = new ReferenceDoubleType(); - - - public static final ScalarType SHORT_TYPE = new ShortType(); - public static final ScalarType REFERENCE_SHORT_TYPE = new ReferenceShortType(); - - - public static final ScalarType BYTE_TYPE = new ByteType(); - public static final ScalarType REFERENCE_BYTE_TYPE = new ReferenceByteType(); - - public static final ScalarType CHAR_TYPE = new CharType(); - public static final ScalarType REFERENCE_CHAR_TYPE = new ReferenceCharType(); - - - public static final ScalarType URL_TYPE = new URLType(); - - public static final ScalarType PARSED_URL_TYPE = new ParsedURLType(); - - public static final ScalarType FILE_TYPE = new FileType(); - - public static final ScalarType BINARY_DATA_TYPE = new BinaryDataType(); - - public static final ScalarType UUID_TYPE = new UUIDType(); - - public static final ScalarType DATE_TYPE = new DateType(); - - public static final ScalarType SCALAR_TYPE_TYPE = new ScalarTypeType(); - - public static final ScalarType COLLECTION_TYPE_TYPE = new CollectionTypeType(); - - public static final ScalarType PATTERN_TYPE = new PatternType(); - - public static final ScalarType ENUMERATED_TYPE = new EnumeratedType(); - - public static final ScalarType CLASS_TYPE = new ClassType(); - - public static final ScalarType FIELD_TYPE = new FieldType(); - - public static final ScalarType COMPOSITE_AS_SCALAR_TYPE = new CompositeAsScalarType(); - +package ecologylab.serialization.types; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.URL; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.UUID; +import java.util.regex.Pattern; + +import ecologylab.collections.Scope; +import ecologylab.generic.HashMapArrayList; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.types.scalar.*; + +public class FundamentalTypes +implements CrossLanguageTypeConstants +{ + public static final CollectionType ARRAYLIST_TYPE = + new CollectionType(ArrayList.class, DOTNET_ARRAYLIST, OBJC_ARRAYLIST); + + public static final CollectionType HASHMAP_TYPE = + new CollectionType(HashMap.class, DOTNET_HASHMAP, OBJC_HASHMAP); + + public static final CollectionType HASHMAPARRAYLIST_TYPE = + new CollectionType( HashMapArrayList.class, DOTNET_HASHMAPARRAYLIST, OBJC_HASHMAPARRAYLIST); + + public static final CollectionType SCOPE_TYPE = + new CollectionType(Scope.class, DOTNET_SCOPE, OBJC_SCOPE); + + static + { + TypeRegistry.setDefaultCollectionType(ARRAYLIST_TYPE); + TypeRegistry.setDefaultMapType(HASHMAP_TYPE); + } + + public static final ScalarType STRING_TYPE = new StringType(); + + public static final ScalarType STRING_BUILDER_TYPE = new StringBuilderType(); + + public static final ScalarType INT_TYPE = new IntType(); + + public static final ScalarType REFERENCE_INTEGER_TYPE = new ReferenceIntegerType(); + + public static final ScalarType LONG_TYPE = new LongType(); + + public static final ScalarType REFERENCE_LONG_TYPE = new ReferenceLongType(); + + public static final ScalarType BOOLEAN_TYPE = new BooleanType(); + + public static final ScalarType REFERENCE_BOOLEAN_TYPE = new ReferenceBooleanType(); + + public static final ScalarType FLOAT_TYPE = new FloatType(); + + public static final ScalarType REFERENCE_FLOAT_TYPE = new ReferenceFloatType(); + + public static final ScalarType DOUBLE_TYPE = new DoubleType(); + + public static final ScalarType REFERENCE_DOUBLE_TYPE = new ReferenceDoubleType(); + + + public static final ScalarType SHORT_TYPE = new ShortType(); + public static final ScalarType REFERENCE_SHORT_TYPE = new ReferenceShortType(); + + + public static final ScalarType BYTE_TYPE = new ByteType(); + public static final ScalarType REFERENCE_BYTE_TYPE = new ReferenceByteType(); + + public static final ScalarType CHAR_TYPE = new CharType(); + public static final ScalarType REFERENCE_CHAR_TYPE = new ReferenceCharType(); + + + public static final ScalarType URL_TYPE = new URLType(); + + public static final ScalarType PARSED_URL_TYPE = new ParsedURLType(); + + public static final ScalarType FILE_TYPE = new FileType(); + + public static final ScalarType BINARY_DATA_TYPE = new BinaryDataType(); + + public static final ScalarType UUID_TYPE = new UUIDType(); + + public static final ScalarType DATE_TYPE = new DateType(); + + public static final ScalarType SCALAR_TYPE_TYPE = new ScalarTypeType(); + + public static final ScalarType COLLECTION_TYPE_TYPE = new CollectionTypeType(); + + public static final ScalarType PATTERN_TYPE = new PatternType(); + + public static final ScalarType ENUMERATED_TYPE = new EnumeratedType(); + + public static final ScalarType CLASS_TYPE = new ClassType(); + + public static final ScalarType FIELD_TYPE = new FieldType(); + + public static final ScalarType COMPOSITE_AS_SCALAR_TYPE = new CompositeAsScalarType(); + } \ No newline at end of file diff --git a/simplCore/src/ecologylab/serialization/types/ScalarType.java b/simplCore/src/ecologylab/serialization/types/ScalarType.java index 7b935215..e64f945c 100644 --- a/simplCore/src/ecologylab/serialization/types/ScalarType.java +++ b/simplCore/src/ecologylab/serialization/types/ScalarType.java @@ -1,566 +1,573 @@ -/* - * Created on Dec 31, 2004 - */ -package ecologylab.serialization.types; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.regex.Pattern; - -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; - -/** - * Basic unit of the scalar type system. Manages marshalling from a Java class that represents a - * scalar, to a String, and from a String to that Java class. - *

- * The ScalarType object is a means for associating a type name with a type index. It also knows how - * to create an instance of the type, given a String representation. If the ScalarType is a - * reference type, this is done with getInstance(String); if the ScalarType is a primitive, this is - * done with getValue(String), which cannot appear as a method in this, the base class, because it - * will return a different primitive type for each such Type. - *

- * Note: unlike with ElementState subtypes, translation of these is controlled entirely by the name - * of the underlying Java class that gets translated, and not by the class name of subclasses of - * this. - * - * @author andruid - */ -@simpl_inherit -public abstract class ScalarType extends SimplType -implements CrossLanguageTypeConstants -{ - @simpl_scalar - boolean isPrimitive; - - - /** - * Blank constructor for S.IM.PL deserialization. - */ - public ScalarType() - { - - } - /** - * Constructor is protected because there should only be 1 instance that gets re-used, for each - * type. To get the instance of this type object for use in translations, call - * TypeRegistry.get("type-string"). - * @param cSharpTypeName TODO - * @param cSharpTypeName TODO - * @param objectiveCTypeName TODO - * @param objectiveCTypeName TODO - * @param dbTypeName TODO - * @param dbTypeName TODO - * - */ - protected ScalarType(Class javaClass, String cSharpTypeName, String objectiveCTypeName, String dbTypeName) - { - super(javaClass, true, cSharpTypeName, objectiveCTypeName, dbTypeName); - - this.isPrimitive = javaClass.isPrimitive(); - } - - protected ScalarType(Class thatClass) - { - this(thatClass, null, null, null); - } - - /** - * If this is a reference type, build an appropriate Object, given a String - * representation. If it is a primitive type, return a boxed value. - * - * @param value - * String representation of the instance. - * @param formatStrings - * Array of formatting values. - * @param scalarUnmarshallingContext - * TODO - */ - abstract public T getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext); - - /** - * Construct an instance, using the subclass of this for marshalling, with null for the format - * Strings. - * - * @param value - * @return - */ - public T getInstance(String value) - { - return getInstance(value, null, null); - } - - /** - * Set the field in the context, using the valueString, converting it to the appropriate type - * using a subclass of this. - *

- * Many different types of exceptions may be thrown. These include IllegalAccessException on the - * one hand, which would come from problems with using reflection to access the Field. This is - * very unlikely. - *

- * More likely are problems with conversion of the parameter value into into an object or - * primitive of the proper type. - * - * @param context - * The object whose field should be modified. - * @param field - * The field to be set. - * @param valueString - * String representation of the value to set the field to. This Type will convert the - * value to the appropriate type, using getInstance(String) for reference types, and type - * specific getValue(String) methods for primitive types. - * @param scalarUnmarshallingContext - * TODO - * @return true if the field is set properly, or if the parameter value that is passed in is null. - * false if the field cannot be accessed, or if value cannot be converted to the - * appropriate type. - */ - public boolean setField(Object context, Field field, String valueString, String[] format, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - boolean result = false; - T referenceObject; - - try - { - if(valueString == null) - { - field.set(context, null); - result = true; - } - else - { - referenceObject = getInstance(valueString, format, scalarUnmarshallingContext); - if (referenceObject != null) - { - field.set(context, referenceObject); - result = true; - } - } - } - catch (Exception e) - { - setFieldError(field, valueString, e); - } - return result; - } - - /** - * Set the field in the context, using the valueString, converting it to the appropriate type - * using a subclass of this. - *

- * The format annotations passed through to the ScalarType subclass will be null. - *

- * Many different types of exceptions may be thrown. These include IllegalAccessException on the - * one hand, which would come from problems with using reflection to access the Field. This is - * very unlikely. - *

- * More likely are problems with conversion of the parameter value into into an object or - * primitive of the proper type. - * - * @param context - * The object whose field should be modified. - * @param field - * The field to be set. - * @param valueString - * String representation of the value to set the field to. This Type will convert the - * value to the appropriate type, using getInstance(String) for reference types, and type - * specific getValue(String) methods for primitive types. - * - * @return true if the field is set properly, or if the parameter value that is passed in is null. - * false if the field cannot be accessed, or if value cannot be converted to the - * appropriate type. - */ - public boolean setField(Object object, Field field, String value) - { - return setField(object, field, value, null, null); - } - - /** - * Display an error message that arose while setting field to value. - * - * @param field - * @param value - * @param e - */ - protected void setFieldError(Field field, String value, Exception e) - { - error("Got " + e + " while trying to set field " + field + " to " + value); - } - - /** - * @return Returns the integer index associated with this type. - */ - /* - * public int getIndex() { return index; } - */ - /** - * Find out if this is a reference type or a primitive types. - * - * @return true for a primitive type. false for a reference type. - */ - public boolean isPrimitive() - { - return isPrimitive; - } - - /** - * Return true if this type may need escaping when emitted as XML. - * - * @return true, by default, for all reference types (includes Strings, PURLs, ...); false - * otherwise. - */ - public boolean needsEscaping() - { - return isReference(); - } - - /** - * Find out if this is a reference type or a primitive types. - * - * @return true for a reference type. false for a primitive type. - */ - public boolean isReference() - { - return !isPrimitive; - } - - /** - * The string representation for a Field of this type. Reference scalar types should NOT override - * this. They should simply override marshall(instance), which this method calls. - *

- * Primitive types cannot create such an instance, from the value of a field, and so must - * override. - */ - public String toString(Field field, Object context) - { - String result = "COULDNT CONVERT!"; - try - { - T instance = (T) field.get(context); - if (instance == null) - result = defaultValueString(); - else - result = marshall(instance, null); - } - catch (Exception e) - { - e.printStackTrace(); - } - return result; - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - *

- * Should only be called *after* checking !isDefault() yourself. - * - * @param buffy - * @param context - * @param serializationContext TODO - * @param field - * @param needsEscaping - * TODO - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, TranslationContext serializationContext, Format format) - throws IllegalArgumentException, IllegalAccessException, IOException - { - Object instance = fieldDescriptor.getValue(context); - appendValue((T) instance, buffy, !fieldDescriptor.isCDATA(), serializationContext, format); - } - - /** - * Get a String representation of the instance, using this. The default just calls the toString() - * method on the instance. - * - * @param instance - * @param serializationContext TODO - * @return - */ - public String marshall(T instance, TranslationContext serializationContext) - { - return instance.toString(); - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - *

- * Should only be called *after* checking !isDefault() yourself. - * - * @param buffy - * @param field - * @param context - * @param needsEscaping - * TODO - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - public void appendValue(StringBuilder buffy, FieldDescriptor fieldDescriptor, Object context) - throws IllegalArgumentException, IllegalAccessException - { - try - { - Object instance = fieldDescriptor.getField().get(context); - - appendValue((T) instance, buffy, !fieldDescriptor.isCDATA(), null); - } - catch (IllegalArgumentException e) - { - throw e; - } - } - - public void appendValue(T instance, StringBuilder buffy, boolean needsEscaping, TranslationContext serializationContext) - { - buffy.append(marshall(instance, serializationContext)); - } - - public void appendValue(T instance, Appendable appendable, boolean needsEscaping, TranslationContext serializationContext, Format format) - throws IOException - { - appendable.append(marshall(instance, serializationContext)); - } - - /** - * The default value for this type, as a String. This value is the one that translateToXML(...) - * wont bother emitting. - */ - public String defaultValueString() - { - return null; - } - - /** - * The default value for this, in its own type. Not meaningful for primitive types. - * - * @return - */ - public T defaultValue() - { - return null; - } - - public final int defaultValueLength() - { - return defaultValueString() == null ? 0 : defaultValueString().length(); - } - - public boolean isDefaultValue(Object value) - { - T defaultValue = this.defaultValue(); - if(defaultValue == null) - { - return value == null; - } - else - { - return defaultValue.equals(value); - } - } - - public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, - IllegalAccessException - { - Object fieldValue = field.get(context); - return isDefaultValue(fieldValue); - } - - /** - * Returns whether or not this is a floating point value of some sort; Types that are floating - * point values should override this method to return true. - * - * The implication of returning true is that the precision of this can be controlled when it is - * emitted as XML. - * - * @return false - */ - public boolean isFloatingPoint() - { - return false; - } - - public boolean allowNewLines() - { - return true; - } - - public static final String DEFAULT_DELIMS = " \n\t"; - - public static final Pattern DEFAULT_DELIMS_TOKENIZER = Pattern.compile("([" + DEFAULT_DELIMS - + "]*)([^" + DEFAULT_DELIMS + "]+)"); - - public static final String MINIMAL_DELIM = " "; - - /** - * For editing: these are the valid delimiters for separating tokens that make up a field of this - * type. - * - * @return - */ - public Pattern delimitersTokenizer() - { - return DEFAULT_DELIMS_TOKENIZER; - } - - public String delimeters() - { - return DEFAULT_DELIMS; - } - - /** - * The most basic and fundamental delimiter to use between characters. - * - * @return The base implementation, here, returns a space. - */ - public String primaryDelimiter() - { - return MINIMAL_DELIM; - } - - /** - * When editing, determines whether delimiters can be included in token strings. - * - * @return - */ - // FIXME -- Add String delimitersAfter to TextChunk -- interleaved with TextTokens, and - // get rid of this!!! - public boolean allowDelimitersInTokens() - { - return false; - } - - /** - * When editing, do not allow the user to include these characters in the resulting value String. - * - * @return - */ - public String illegalChars() - { - return ""; - } - - /** - * When editing, is the field one that should be part of the Term model? - * - * @return true for Strings - */ - public boolean composedOfTerms() - { - return true; - } - - String fieldTypeName; - - public String fieldTypeName() - { - String result = fieldTypeName; - if (result == null) - { - result = this.getSimpleName(); - int index = result.indexOf("Type"); - if (index != -1) - { - result = result.substring(0, index); - } - // if (isPrimitive()) - // { - // char first = Character.toLowerCase(result.charAt(0)); - // if (result.length() > 1) - // result = first + result.substring(1); - // else - // result = Character.toString(first); - // } - fieldTypeName = result; - } - return result; - } - - /** - * Used to describe scalar types used for serializing the type system, itself. They cannot be - * unmarshalled in Java, only marshalled. Code may be written to access their String - * representations in other languages. - * - * @return false for almost all ScalarTypes - */ - public boolean isMarshallOnly() - { - return false; - } - - public ScalarType operativeScalarType() - { - return this; - } - - /** - * Used to fill seams between direct scalar types, and those with a nested field that actually - * stores the value. - * - * @param externalField - * @return Depending on the type, either the external field, or one within the type. - */ - public Field operativeField(Field externalField) - { - return externalField; - } - - /** - * Used to fill seams between direct scalar types, and those with a nested field that actually - * stores the value. - * - * @param largerContext - * @param field - * - * @return Depending on the type, the larger context passed in, or the object value of the field - * within the context. - */ - public T unpackContext(Object largerContext, Field field) - { - return (T) largerContext; - } - - protected static String getNullStringIfNull(FieldDescriptor fieldDescriptor, Object context) - throws IllegalArgumentException, IllegalAccessException - { - return (fieldDescriptor.getField() == null || fieldDescriptor.getField().get(context) == null) ? "null" : null; - } - - /** - * The name to use when declaring a field in C# cross-compilation. - * For ScalarType, be aggressive in seeking a suitable type name. - * - * @return cSharpTypeName, if one was passed in explicitly. otherwise, assume its the same as javaTypeName, and pass that. - */ - @Override - public String deriveCSharpTypeName() - { - String cSharpTypeName = super.getCSharpTypeName(); - return cSharpTypeName != null ? cSharpTypeName : super.getJavaTypeName(); - } - - /** - * The name to use when declaring a field in Objective C cross-compilation. - * For ScalarType, be aggressive in seeking a suitable type name. - * - * @return objectiveCTypeName, if one was passed in explicitly. otherwise, assume its the same as simple name, and pass that. - */ - @Override - public String deriveObjectiveCTypeName() - { - String objectiveCTypeName = super.getObjectiveCTypeName(); - return objectiveCTypeName != null ? objectiveCTypeName : super.getSimpleName(); - } - - @Override - public boolean isScalar() - { - return true; - } -} +/* + * Created on Dec 31, 2004 + */ +package ecologylab.serialization.types; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.regex.Pattern; + +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +/** + * Basic unit of the scalar type system. Manages marshalling from a Java class that represents a + * scalar, to a String, and from a String to that Java class. + *

+ * The ScalarType object is a means for associating a type name with a type index. It also knows how + * to create an instance of the type, given a String representation. If the ScalarType is a + * reference type, this is done with getInstance(String); if the ScalarType is a primitive, this is + * done with getValue(String), which cannot appear as a method in this, the base class, because it + * will return a different primitive type for each such Type. + *

+ * Note: unlike with ElementState subtypes, translation of these is controlled entirely by the name + * of the underlying Java class that gets translated, and not by the class name of subclasses of + * this. + * + * @author andruid + */ +@simpl_inherit +public abstract class ScalarType extends SimplType +implements CrossLanguageTypeConstants +{ + @simpl_scalar + boolean isPrimitive; + + @simpl_scalar + protected boolean needJsonSerializationQuotation = true; + + /** + * Blank constructor for S.IM.PL deserialization. + */ + public ScalarType() + { + + } + /** + * Constructor is protected because there should only be 1 instance that gets re-used, for each + * type. To get the instance of this type object for use in translations, call + * TypeRegistry.get("type-string"). + * @param cSharpTypeName TODO + * @param cSharpTypeName TODO + * @param objectiveCTypeName TODO + * @param objectiveCTypeName TODO + * @param dbTypeName TODO + * @param dbTypeName TODO + * + */ + protected ScalarType(Class javaClass, String cSharpTypeName, String objectiveCTypeName, String dbTypeName) + { + super(javaClass, true, cSharpTypeName, objectiveCTypeName, dbTypeName); + + this.isPrimitive = javaClass.isPrimitive(); + } + + protected ScalarType(Class thatClass) + { + this(thatClass, null, null, null); + } + + /** + * If this is a reference type, build an appropriate Object, given a String + * representation. If it is a primitive type, return a boxed value. + * + * @param value + * String representation of the instance. + * @param formatStrings + * Array of formatting values. + * @param scalarUnmarshallingContext + * TODO + */ + abstract public T getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext); + + /** + * Construct an instance, using the subclass of this for marshalling, with null for the format + * Strings. + * + * @param value + * @return + */ + public T getInstance(String value) + { + return getInstance(value, null, null); + } + + /** + * Set the field in the context, using the valueString, converting it to the appropriate type + * using a subclass of this. + *

+ * Many different types of exceptions may be thrown. These include IllegalAccessException on the + * one hand, which would come from problems with using reflection to access the Field. This is + * very unlikely. + *

+ * More likely are problems with conversion of the parameter value into into an object or + * primitive of the proper type. + * + * @param context + * The object whose field should be modified. + * @param field + * The field to be set. + * @param valueString + * String representation of the value to set the field to. This Type will convert the + * value to the appropriate type, using getInstance(String) for reference types, and type + * specific getValue(String) methods for primitive types. + * @param scalarUnmarshallingContext + * TODO + * @return true if the field is set properly, or if the parameter value that is passed in is null. + * false if the field cannot be accessed, or if value cannot be converted to the + * appropriate type. + */ + public boolean setField(Object context, Field field, String valueString, String[] format, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + boolean result = false; + T referenceObject; + + try + { + if(valueString == null) + { + field.set(context, null); + result = true; + } + else + { + referenceObject = getInstance(valueString, format, scalarUnmarshallingContext); + if (referenceObject != null) + { + field.set(context, referenceObject); + result = true; + } + } + } + catch (Exception e) + { + setFieldError(field, valueString, e); + } + return result; + } + + /** + * Set the field in the context, using the valueString, converting it to the appropriate type + * using a subclass of this. + *

+ * The format annotations passed through to the ScalarType subclass will be null. + *

+ * Many different types of exceptions may be thrown. These include IllegalAccessException on the + * one hand, which would come from problems with using reflection to access the Field. This is + * very unlikely. + *

+ * More likely are problems with conversion of the parameter value into into an object or + * primitive of the proper type. + * + * @param context + * The object whose field should be modified. + * @param field + * The field to be set. + * @param valueString + * String representation of the value to set the field to. This Type will convert the + * value to the appropriate type, using getInstance(String) for reference types, and type + * specific getValue(String) methods for primitive types. + * + * @return true if the field is set properly, or if the parameter value that is passed in is null. + * false if the field cannot be accessed, or if value cannot be converted to the + * appropriate type. + */ + public boolean setField(Object object, Field field, String value) + { + return setField(object, field, value, null, null); + } + + /** + * Display an error message that arose while setting field to value. + * + * @param field + * @param value + * @param e + */ + protected void setFieldError(Field field, String value, Exception e) + { + error("Got " + e + " while trying to set field " + field + " to " + value); + } + + /** + * @return Returns the integer index associated with this type. + */ + /* + * public int getIndex() { return index; } + */ + /** + * Find out if this is a reference type or a primitive types. + * + * @return true for a primitive type. false for a reference type. + */ + public boolean isPrimitive() + { + return isPrimitive; + } + + /** + * Return true if this type may need escaping when emitted as XML. + * + * @return true, by default, for all reference types (includes Strings, PURLs, ...); false + * otherwise. + */ + public boolean needsEscaping() + { + return isReference(); + } + + /** + * Find out if this is a reference type or a primitive types. + * + * @return true for a reference type. false for a primitive type. + */ + public boolean isReference() + { + return !isPrimitive; + } + + /** + * The string representation for a Field of this type. Reference scalar types should NOT override + * this. They should simply override marshall(instance), which this method calls. + *

+ * Primitive types cannot create such an instance, from the value of a field, and so must + * override. + */ + public String toString(Field field, Object context) + { + String result = "COULDNT CONVERT!"; + try + { + T instance = (T) field.get(context); + if (instance == null) + result = defaultValueString(); + else + result = marshall(instance, null); + } + catch (Exception e) + { + e.printStackTrace(); + } + return result; + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + *

+ * Should only be called *after* checking !isDefault() yourself. + * + * @param buffy + * @param context + * @param serializationContext TODO + * @param field + * @param needsEscaping + * TODO + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, TranslationContext serializationContext, Format format) + throws IllegalArgumentException, IllegalAccessException, IOException + { + Object instance = fieldDescriptor.getValue(context); + appendValue((T) instance, buffy, !fieldDescriptor.isCDATA(), serializationContext, format); + } + + /** + * Get a String representation of the instance, using this. The default just calls the toString() + * method on the instance. + * + * @param instance + * @param serializationContext TODO + * @return + */ + public String marshall(T instance, TranslationContext serializationContext) + { + return instance.toString(); + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + *

+ * Should only be called *after* checking !isDefault() yourself. + * + * @param buffy + * @param field + * @param context + * @param needsEscaping + * TODO + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + public void appendValue(StringBuilder buffy, FieldDescriptor fieldDescriptor, Object context) + throws IllegalArgumentException, IllegalAccessException + { + try + { + Object instance = fieldDescriptor.getField().get(context); + + appendValue((T) instance, buffy, !fieldDescriptor.isCDATA(), null); + } + catch (IllegalArgumentException e) + { + throw e; + } + } + + public void appendValue(T instance, StringBuilder buffy, boolean needsEscaping, TranslationContext serializationContext) + { + buffy.append(marshall(instance, serializationContext)); + } + + public void appendValue(T instance, Appendable appendable, boolean needsEscaping, TranslationContext serializationContext, Format format) + throws IOException + { + appendable.append(marshall(instance, serializationContext)); + } + + /** + * The default value for this type, as a String. This value is the one that translateToXML(...) + * wont bother emitting. + */ + public String defaultValueString() + { + return null; + } + + /** + * The default value for this, in its own type. Not meaningful for primitive types. + * + * @return + */ + public T defaultValue() + { + return null; + } + + public final int defaultValueLength() + { + return defaultValueString() == null ? 0 : defaultValueString().length(); + } + + public boolean isDefaultValue(Object value) + { + T defaultValue = this.defaultValue(); + if(defaultValue == null) + { + return value == null; + } + else + { + return defaultValue.equals(value); + } + } + + public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, + IllegalAccessException + { + Object fieldValue = field.get(context); + return isDefaultValue(fieldValue); + } + + /** + * Returns whether or not this is a floating point value of some sort; Types that are floating + * point values should override this method to return true. + * + * The implication of returning true is that the precision of this can be controlled when it is + * emitted as XML. + * + * @return false + */ + public boolean isFloatingPoint() + { + return false; + } + + public boolean allowNewLines() + { + return true; + } + + public static final String DEFAULT_DELIMS = " \n\t"; + + public static final Pattern DEFAULT_DELIMS_TOKENIZER = Pattern.compile("([" + DEFAULT_DELIMS + + "]*)([^" + DEFAULT_DELIMS + "]+)"); + + public static final String MINIMAL_DELIM = " "; + + /** + * For editing: these are the valid delimiters for separating tokens that make up a field of this + * type. + * + * @return + */ + public Pattern delimitersTokenizer() + { + return DEFAULT_DELIMS_TOKENIZER; + } + + public String delimeters() + { + return DEFAULT_DELIMS; + } + + /** + * The most basic and fundamental delimiter to use between characters. + * + * @return The base implementation, here, returns a space. + */ + public String primaryDelimiter() + { + return MINIMAL_DELIM; + } + + /** + * When editing, determines whether delimiters can be included in token strings. + * + * @return + */ + // FIXME -- Add String delimitersAfter to TextChunk -- interleaved with TextTokens, and + // get rid of this!!! + public boolean allowDelimitersInTokens() + { + return false; + } + + /** + * When editing, do not allow the user to include these characters in the resulting value String. + * + * @return + */ + public String illegalChars() + { + return ""; + } + + /** + * When editing, is the field one that should be part of the Term model? + * + * @return true for Strings + */ + public boolean composedOfTerms() + { + return true; + } + + String fieldTypeName; + + public String fieldTypeName() + { + String result = fieldTypeName; + if (result == null) + { + result = this.getSimpleName(); + int index = result.indexOf("Type"); + if (index != -1) + { + result = result.substring(0, index); + } + // if (isPrimitive()) + // { + // char first = Character.toLowerCase(result.charAt(0)); + // if (result.length() > 1) + // result = first + result.substring(1); + // else + // result = Character.toString(first); + // } + fieldTypeName = result; + } + return result; + } + + /** + * Used to describe scalar types used for serializing the type system, itself. They cannot be + * unmarshalled in Java, only marshalled. Code may be written to access their String + * representations in other languages. + * + * @return false for almost all ScalarTypes + */ + public boolean isMarshallOnly() + { + return false; + } + + public ScalarType operativeScalarType() + { + return this; + } + + /** + * Used to fill seams between direct scalar types, and those with a nested field that actually + * stores the value. + * + * @param externalField + * @return Depending on the type, either the external field, or one within the type. + */ + public Field operativeField(Field externalField) + { + return externalField; + } + + /** + * Used to fill seams between direct scalar types, and those with a nested field that actually + * stores the value. + * + * @param largerContext + * @param field + * + * @return Depending on the type, the larger context passed in, or the object value of the field + * within the context. + */ + public T unpackContext(Object largerContext, Field field) + { + return (T) largerContext; + } + + protected static String getNullStringIfNull(FieldDescriptor fieldDescriptor, Object context) + throws IllegalArgumentException, IllegalAccessException + { + return (fieldDescriptor.getField() == null || fieldDescriptor.getField().get(context) == null) ? "null" : null; + } + + /** + * The name to use when declaring a field in C# cross-compilation. + * For ScalarType, be aggressive in seeking a suitable type name. + * + * @return cSharpTypeName, if one was passed in explicitly. otherwise, assume its the same as javaTypeName, and pass that. + */ + @Override + public String deriveCSharpTypeName() + { + String cSharpTypeName = super.getCSharpTypeName(); + return cSharpTypeName != null ? cSharpTypeName : super.getJavaTypeName(); + } + + /** + * The name to use when declaring a field in Objective C cross-compilation. + * For ScalarType, be aggressive in seeking a suitable type name. + * + * @return objectiveCTypeName, if one was passed in explicitly. otherwise, assume its the same as simple name, and pass that. + */ + @Override + public String deriveObjectiveCTypeName() + { + String objectiveCTypeName = super.getObjectiveCTypeName(); + return objectiveCTypeName != null ? objectiveCTypeName : super.getSimpleName(); + } + + @Override + public boolean isScalar() + { + return true; + } + + public boolean needJsonSerializationQuotation() + { + return needJsonSerializationQuotation; + } +} diff --git a/simplCore/src/ecologylab/serialization/types/TypeRegistry.java b/simplCore/src/ecologylab/serialization/types/TypeRegistry.java index f4898d34..5dada52e 100644 --- a/simplCore/src/ecologylab/serialization/types/TypeRegistry.java +++ b/simplCore/src/ecologylab/serialization/types/TypeRegistry.java @@ -1,358 +1,358 @@ -package ecologylab.serialization.types; - -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.Map; - -import ecologylab.generic.Debug; -import ecologylab.platformspecifics.FundamentalPlatformSpecifics; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.types.scalar.CompositeAsScalarType; - -/** - * This class implements registries of instances of ScalarType and CollectionType. - *

- * Thus, for example, the key for the type translated by IntType is "int", not "IntType". - * (But for the type translated by IntegerType, it is Integer :-) - * It must be - * this way, because automatic translation is performed based on Field declarations, and the Field - * declarations do not know about these Types, only about the underlying Java types. - */ -public class TypeRegistry extends Debug -implements CrossLanguageTypeConstants -{ - /** - * This is now a doubleton class, like a singleton, but there are 2. - * One instance for ScalarType, one instance for CollectionType. - */ - private static TypeRegistry scalarRegistry; - - private static TypeRegistry collectionRegistry; - - /** - * These are by Java full name. - */ - private final HashMap typesByJavaName = new HashMap(); - - private final HashMap typesByCrossPlatformName = new HashMap(); - - private final HashMap typesBySimpleName = new HashMap(); - - private final HashMap typesByCSharpName = new HashMap(); - - private final HashMap typesByObjectiveCName = new HashMap(); - - private final HashMap typesByDbName = new HashMap(); - - private CollectionType defaultCollectionType, defaultMapType; - - static - { - init(); - } - private static boolean init; - - /** - * - */ - public static void init() - { - if (!init) - { - init = true; - - new FundamentalTypes(); - - FundamentalPlatformSpecifics.get().initializePlatformSpecificTypes(); - } - } - - public TypeRegistry() - { - - } - - private static TypeRegistry scalarRegistry() - { - TypeRegistry result = scalarRegistry; - if (result == null) - { - synchronized (TypeRegistry.class) - { - result = scalarRegistry; - if (result == null) - { - result = new TypeRegistry(); - scalarRegistry = result; - } - } - } - return result; - } - - private static TypeRegistry collectionRegistry() - { - TypeRegistry result = collectionRegistry; - if (result == null) - { - synchronized (TypeRegistry.class) - { - result = collectionRegistry; - if (result == null) - { - result = new TypeRegistry(); - collectionRegistry = result; - } - } - } - return result; - } - static boolean registerSimplType(SimplType type) - { - TypeRegistry registry = CollectionType.class.isAssignableFrom(type.getClass()) ? collectionRegistry() : scalarRegistry(); - - return registry.registerType(type); - } - /** - * Enter this type in the registry, which is a map in which the Type's Class object's fully - * qualified named is used as a key. - */ - static boolean registerScalarType(ScalarType type) - { - return scalarRegistry().registerType(type); - } - - private synchronized boolean registerTypeIfNew(ST type) - { - String javaTypeName = type.getJavaTypeName(); - return typesByJavaName.containsKey(javaTypeName) ? false : registerType(type); - } - private synchronized boolean registerType(ST type) - { - String javaTypeName = type.getJavaTypeName(); - typesByJavaName.put(javaTypeName, type); - - String crossPlatformName = type.getName(); - typesByCrossPlatformName.put(crossPlatformName, type); - - String cSharpTypeName = type.getCSharpTypeName(); - if (cSharpTypeName != null) - typesByCSharpName.put(cSharpTypeName, type); - - String objectiveCTypeName = type.getObjectiveCTypeName(); - if (objectiveCTypeName != null) - typesByObjectiveCName.put(objectiveCTypeName, type); - - String dbTypeName = type.getDbTypeName(); - if (dbTypeName != null) - typesByDbName.put(dbTypeName, type); - - String simpleName = type.getSimpleName(); - ST previous = typesBySimpleName.put(simpleName, type); - boolean definingNewType = previous != null && !previous.equals(type); - if (definingNewType) - { - warning("registerType(): Redefining type: " + simpleName); - } - return definingNewType; - } - /** - * Get the Scalar Type corresponding to the Class, by using its name. - * - * @param thatClass - * @return Type associated with thatClass - */ - public static ScalarType getScalarType(Class thatClass) - { - if (XMLTools.isEnum(thatClass)) - { - return scalarRegistry().getTypeByClass(Enum.class); - } - else - { - ScalarType result = scalarRegistry().getTypeByClass(thatClass); - if (result == null && XMLTools.isComposite(thatClass)) - result = scalarRegistry().getTypeByClass(CompositeAsScalarType.class); - - return result; - } - } - - /** - * Check to see if we have a Type corresponding to the Class, by using its name. - * - * @param thatClass - * @return true if thatClass is in this TypeRegistry - */ - public static boolean containsScalarType(Class thatClass) - { - return scalarRegistry().contains(thatClass); - } - - public static ScalarType getScalarTypeByName(String name) - { - return scalarRegistry().getTypeByJavaName(name); - } - public static ScalarType getScalarTypeBySimpleName(String simpleName) - { - return scalarRegistry().getTypeBySimpleName(simpleName); - } - - ST getTypeBySimpleName(String simpleName) - { - return typesBySimpleName.get(simpleName); - } - - boolean contains(Class javaClass) - { - return containsByJavaName(javaClass.getName()); - } - boolean containsByJavaName(String javaName) - { - return typesByJavaName.containsKey(javaName); - } - ST getTypeByClass(Class javaClass) - { - return getTypeByJavaName(javaClass.getName()); - } - - ST getTypeByJavaName(String javaName) - { - return typesByJavaName.get(javaName); - } - - ST getTypeByCSharpName(String cSharpName) - { - return typesByCSharpName.get(cSharpName); - } - - ST getTypeByObjectiveCName(String objectiveCName) - { - return typesByObjectiveCName.get(objectiveCName); - } - - ST getTypeByDbName(String dbName) - { - return typesByDbName.get(dbName); - } - /** - * This method is only called by the constructor of CollectionType. - * - * @param collectionType - */ - static void registerCollectionType(CollectionType collectionType) - { - collectionRegistry().registerType(collectionType); -// TypeRegistry registrySingleton = collectionRegistry(); -// registrySingleton.typesByJavaName.put(collectionType.getName(), collectionType); -// registrySingleton.typesBySimpleName.put(collectionType.getJavaTypeName(), collectionType); - } - - /** - * Get by unique, cross-platform name. - * - * @param crossPlatformName - * @return - */ - public static CollectionType getCollectionTypeByCrossPlatformName(String crossPlatformName) - { - return collectionRegistry().typesByCrossPlatformName.get(crossPlatformName); - } - - public static CollectionType getCollectionTypeByCSharpName(String cSharpName) - { - return collectionRegistry().typesByCSharpName.get(cSharpName); - } - - public static CollectionType getCollectionTypeByObjectiveCName(String objectiveCName) - { - return collectionRegistry().typesByObjectiveCName.get(objectiveCName); - } - - public static CollectionType getCollectionTypeBySimpleName(String simpleName) - { - return collectionRegistry().typesBySimpleName.get(simpleName); - } - - /** - * Lookup a collection type using the Java class or its full unqualifiedName. - * - * @param javaField Declaring class of this field is key for lookup - * - * @return - */ - public static CollectionType getCollectionType(Field javaField) - { - return getCollectionType(javaField.getType()); - } - - /** - * Lookup a collection type using the Java class or its full unqualifiedName. - * If it does not exist, construct a new CollectionType, but with no capabilities for Cross-Language Code Generation. - * - * @param javaClass - * @return - */ - public static CollectionType getCollectionType(Class javaClass) - { - String javaClassName = javaClass.getName(); - CollectionType result = getCollectionTypeByJavaName(javaClassName); - if (result == null) - { - if (javaClass.isInterface() || Modifier.isAbstract(javaClass.getModifiers())) - { - return Map.class.isAssignableFrom(javaClass) ? collectionRegistry().defaultMapType : collectionRegistry().defaultCollectionType; - } - else - { - String crossPlatformName = SimplType.deriveCrossPlatformName(javaClass, false); - collectionRegistry().warning("No CollectionType was pre-defined for " + crossPlatformName + ", so constructing one on the fly.\nCross-language code for fields defined with this type cannot be generated."); - result = new CollectionType(javaClass, null, null); - } - } - return result; - } - /** - * Lookup a collection type using the Java class or its full unqualifiedName. - * - * @param javaClassName - * @return - */ - public static CollectionType getCollectionTypeByJavaName(String javaClassName) - { - return collectionRegistry().typesByJavaName.get(javaClassName); - } - - public static TypeRegistry typeRegistry() - { - return scalarRegistry; - } - - public static void setDefaultCollectionType(CollectionType ct) - { - collectionRegistry().defaultCollectionType = ct; - } - - public static void setDefaultMapType(CollectionType ct) - { - collectionRegistry().defaultMapType = ct; - } - - static CollectionType getDefaultCollectionType() - { - return collectionRegistry().defaultCollectionType; - } - - static CollectionType getDefaultMapType() - { - return collectionRegistry().defaultMapType; - } - - static CollectionType getDefaultCollectionOrMapType(boolean isMap) - { - return isMap ? getDefaultMapType() : getDefaultCollectionType(); - } - - -} +package ecologylab.serialization.types; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; + +import ecologylab.generic.Debug; +import ecologylab.platformspecifics.FundamentalPlatformSpecifics; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.types.scalar.CompositeAsScalarType; + +/** + * This class implements registries of instances of ScalarType and CollectionType. + *

+ * Thus, for example, the key for the type translated by IntType is "int", not "IntType". + * (But for the type translated by IntegerType, it is Integer :-) + * It must be + * this way, because automatic translation is performed based on Field declarations, and the Field + * declarations do not know about these Types, only about the underlying Java types. + */ +public class TypeRegistry extends Debug +implements CrossLanguageTypeConstants +{ + /** + * This is now a doubleton class, like a singleton, but there are 2. + * One instance for ScalarType, one instance for CollectionType. + */ + private static TypeRegistry scalarRegistry; + + private static TypeRegistry collectionRegistry; + + /** + * These are by Java full name. + */ + private final HashMap typesByJavaName = new HashMap(); + + private final HashMap typesByCrossPlatformName = new HashMap(); + + private final HashMap typesBySimpleName = new HashMap(); + + private final HashMap typesByCSharpName = new HashMap(); + + private final HashMap typesByObjectiveCName = new HashMap(); + + private final HashMap typesByDbName = new HashMap(); + + private CollectionType defaultCollectionType, defaultMapType; + + static + { + init(); + } + private static boolean init; + + /** + * + */ + public static void init() + { + if (!init) + { + init = true; + + new FundamentalTypes(); + + FundamentalPlatformSpecifics.get().initializePlatformSpecificTypes(); + } + } + + public TypeRegistry() + { + + } + + private static TypeRegistry scalarRegistry() + { + TypeRegistry result = scalarRegistry; + if (result == null) + { + synchronized (TypeRegistry.class) + { + result = scalarRegistry; + if (result == null) + { + result = new TypeRegistry(); + scalarRegistry = result; + } + } + } + return result; + } + + private static TypeRegistry collectionRegistry() + { + TypeRegistry result = collectionRegistry; + if (result == null) + { + synchronized (TypeRegistry.class) + { + result = collectionRegistry; + if (result == null) + { + result = new TypeRegistry(); + collectionRegistry = result; + } + } + } + return result; + } + static boolean registerSimplType(SimplType type) + { + TypeRegistry registry = CollectionType.class.isAssignableFrom(type.getClass()) ? collectionRegistry() : scalarRegistry(); + + return registry.registerType(type); + } + /** + * Enter this type in the registry, which is a map in which the Type's Class object's fully + * qualified named is used as a key. + */ + static boolean registerScalarType(ScalarType type) + { + return scalarRegistry().registerType(type); + } + + private synchronized boolean registerTypeIfNew(ST type) + { + String javaTypeName = type.getJavaTypeName(); + return typesByJavaName.containsKey(javaTypeName) ? false : registerType(type); + } + private synchronized boolean registerType(ST type) + { + String javaTypeName = type.getJavaTypeName(); + typesByJavaName.put(javaTypeName, type); + + String crossPlatformName = type.getName(); + typesByCrossPlatformName.put(crossPlatformName, type); + + String cSharpTypeName = type.getCSharpTypeName(); + if (cSharpTypeName != null) + typesByCSharpName.put(cSharpTypeName, type); + + String objectiveCTypeName = type.getObjectiveCTypeName(); + if (objectiveCTypeName != null) + typesByObjectiveCName.put(objectiveCTypeName, type); + + String dbTypeName = type.getDbTypeName(); + if (dbTypeName != null) + typesByDbName.put(dbTypeName, type); + + String simpleName = type.getSimpleName(); + ST previous = typesBySimpleName.put(simpleName, type); + boolean definingNewType = previous != null && !previous.equals(type); + if (definingNewType) + { + warning("registerType(): Redefining type: " + simpleName); + } + return definingNewType; + } + /** + * Get the Scalar Type corresponding to the Class, by using its name. + * + * @param thatClass + * @return Type associated with thatClass + */ + public static ScalarType getScalarType(Class thatClass) + { + if (XMLTools.isEnum(thatClass)) + { + return scalarRegistry().getTypeByClass(Enum.class); + } + else + { + ScalarType result = scalarRegistry().getTypeByClass(thatClass); + if (result == null && XMLTools.isComposite(thatClass)) + result = scalarRegistry().getTypeByClass(CompositeAsScalarType.class); + + return result; + } + } + + /** + * Check to see if we have a Type corresponding to the Class, by using its name. + * + * @param thatClass + * @return true if thatClass is in this TypeRegistry + */ + public static boolean containsScalarType(Class thatClass) + { + return scalarRegistry().contains(thatClass); + } + + public static ScalarType getScalarTypeByName(String name) + { + return scalarRegistry().getTypeByJavaName(name); + } + public static ScalarType getScalarTypeBySimpleName(String simpleName) + { + return scalarRegistry().getTypeBySimpleName(simpleName); + } + + ST getTypeBySimpleName(String simpleName) + { + return typesBySimpleName.get(simpleName); + } + + boolean contains(Class javaClass) + { + return containsByJavaName(javaClass.getName()); + } + boolean containsByJavaName(String javaName) + { + return typesByJavaName.containsKey(javaName); + } + ST getTypeByClass(Class javaClass) + { + return getTypeByJavaName(javaClass.getName()); + } + + ST getTypeByJavaName(String javaName) + { + return typesByJavaName.get(javaName); + } + + ST getTypeByCSharpName(String cSharpName) + { + return typesByCSharpName.get(cSharpName); + } + + ST getTypeByObjectiveCName(String objectiveCName) + { + return typesByObjectiveCName.get(objectiveCName); + } + + ST getTypeByDbName(String dbName) + { + return typesByDbName.get(dbName); + } + /** + * This method is only called by the constructor of CollectionType. + * + * @param collectionType + */ + static void registerCollectionType(CollectionType collectionType) + { + collectionRegistry().registerType(collectionType); +// TypeRegistry registrySingleton = collectionRegistry(); +// registrySingleton.typesByJavaName.put(collectionType.getName(), collectionType); +// registrySingleton.typesBySimpleName.put(collectionType.getJavaTypeName(), collectionType); + } + + /** + * Get by unique, cross-platform name. + * + * @param crossPlatformName + * @return + */ + public static CollectionType getCollectionTypeByCrossPlatformName(String crossPlatformName) + { + return collectionRegistry().typesByCrossPlatformName.get(crossPlatformName); + } + + public static CollectionType getCollectionTypeByCSharpName(String cSharpName) + { + return collectionRegistry().typesByCSharpName.get(cSharpName); + } + + public static CollectionType getCollectionTypeByObjectiveCName(String objectiveCName) + { + return collectionRegistry().typesByObjectiveCName.get(objectiveCName); + } + + public static CollectionType getCollectionTypeBySimpleName(String simpleName) + { + return collectionRegistry().typesBySimpleName.get(simpleName); + } + + /** + * Lookup a collection type using the Java class or its full unqualifiedName. + * + * @param javaField Declaring class of this field is key for lookup + * + * @return + */ + public static CollectionType getCollectionType(Field javaField) + { + return getCollectionType(javaField.getType()); + } + + /** + * Lookup a collection type using the Java class or its full unqualifiedName. + * If it does not exist, construct a new CollectionType, but with no capabilities for Cross-Language Code Generation. + * + * @param javaClass + * @return + */ + public static CollectionType getCollectionType(Class javaClass) + { + String javaClassName = javaClass.getName(); + CollectionType result = getCollectionTypeByJavaName(javaClassName); + if (result == null) + { + if (javaClass.isInterface() || Modifier.isAbstract(javaClass.getModifiers())) + { + return Map.class.isAssignableFrom(javaClass) ? collectionRegistry().defaultMapType : collectionRegistry().defaultCollectionType; + } + else + { + String crossPlatformName = SimplType.deriveCrossPlatformName(javaClass, false); + collectionRegistry().warning("No CollectionType was pre-defined for " + crossPlatformName + ", so constructing one on the fly.\nCross-language code for fields defined with this type cannot be generated."); + result = new CollectionType(javaClass, null, null); + } + } + return result; + } + /** + * Lookup a collection type using the Java class or its full unqualifiedName. + * + * @param javaClassName + * @return + */ + public static CollectionType getCollectionTypeByJavaName(String javaClassName) + { + return collectionRegistry().typesByJavaName.get(javaClassName); + } + + public static TypeRegistry typeRegistry() + { + return scalarRegistry; + } + + public static void setDefaultCollectionType(CollectionType ct) + { + collectionRegistry().defaultCollectionType = ct; + } + + public static void setDefaultMapType(CollectionType ct) + { + collectionRegistry().defaultMapType = ct; + } + + static CollectionType getDefaultCollectionType() + { + return collectionRegistry().defaultCollectionType; + } + + static CollectionType getDefaultMapType() + { + return collectionRegistry().defaultMapType; + } + + static CollectionType getDefaultCollectionOrMapType(boolean isMap) + { + return isMap ? getDefaultMapType() : getDefaultCollectionType(); + } + + +} diff --git a/simplCore/src/ecologylab/serialization/types/element/ElementTypeTranslationsProvider.java b/simplCore/src/ecologylab/serialization/types/element/ElementTypeTranslationsProvider.java index c56485ee..a88ad633 100644 --- a/simplCore/src/ecologylab/serialization/types/element/ElementTypeTranslationsProvider.java +++ b/simplCore/src/ecologylab/serialization/types/element/ElementTypeTranslationsProvider.java @@ -1,48 +1,48 @@ -/** - * - */ -package ecologylab.serialization.types.element; - -import ecologylab.generic.Debug; -import ecologylab.serialization.SimplTypesScope; - -/** - * Translations for built-in element types. - * - * @author andruid - */ -public class ElementTypeTranslationsProvider extends Debug -{ - - /** - * Prevent external calls. Use get(). - */ - private ElementTypeTranslationsProvider() - { - } - - /** - * Package name - */ - private static final String PACKAGE_NAME = "ecologylab.serialization.types.element"; - - /** - * What we should be translating to/from xml - */ - private static final Class TRANSLATIONS[] = - { - IntState.class, - StringState.class, - - }; - - - /** - * Get the translation space - */ - public static SimplTypesScope get() - { - return SimplTypesScope.get(PACKAGE_NAME, TRANSLATIONS); - } - -} +/** + * + */ +package ecologylab.serialization.types.element; + +import ecologylab.generic.Debug; +import ecologylab.serialization.SimplTypesScope; + +/** + * Translations for built-in element types. + * + * @author andruid + */ +public class ElementTypeTranslationsProvider extends Debug +{ + + /** + * Prevent external calls. Use get(). + */ + private ElementTypeTranslationsProvider() + { + } + + /** + * Package name + */ + private static final String PACKAGE_NAME = "ecologylab.serialization.types.element"; + + /** + * What we should be translating to/from xml + */ + private static final Class TRANSLATIONS[] = + { + IntState.class, + StringState.class, + + }; + + + /** + * Get the translation space + */ + public static SimplTypesScope get() + { + return SimplTypesScope.get(PACKAGE_NAME, TRANSLATIONS); + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/element/IMappable.java b/simplCore/src/ecologylab/serialization/types/element/IMappable.java index 8e9c1668..e0efce21 100644 --- a/simplCore/src/ecologylab/serialization/types/element/IMappable.java +++ b/simplCore/src/ecologylab/serialization/types/element/IMappable.java @@ -1,13 +1,13 @@ -/** - * - */ -package ecologylab.serialization.types.element; - -/** - * Implemented by objects that provide a key for automatic insertion into a Map. - * @author andruid - */ -public interface IMappable -{ - public T key(); -} +/** + * + */ +package ecologylab.serialization.types.element; + +/** + * Implemented by objects that provide a key for automatic insertion into a Map. + * @author andruid + */ +public interface IMappable +{ + public T key(); +} diff --git a/simplCore/src/ecologylab/serialization/types/element/IntState.java b/simplCore/src/ecologylab/serialization/types/element/IntState.java index 421068a1..e0efd798 100644 --- a/simplCore/src/ecologylab/serialization/types/element/IntState.java +++ b/simplCore/src/ecologylab/serialization/types/element/IntState.java @@ -1,83 +1,83 @@ -package ecologylab.serialization.types.element; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - - -/** - * Reference version of an int type. Re-writable, unlike java.lang.Integer.

- * Object wrapper for int primitive values. Useful for storing in HashMaps, and - * anywhere else that a reference type is needed. - */ -public class IntState extends ElementState implements Comparable -{ - private @simpl_scalar int value; - - public IntState(int b) - { - super(); - value = b; - } - - /** - * - */ - public IntState() - { - } - - /** - * Returns a hashcode for this Integer. - * - * @return a hash code value for this object. - * @since JDK1.0 - */ - @Override public int hashCode() - { - return value; - } - - @Override public String toString() - { - return "IntState[" + value + "]"; - } - - /** - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override public boolean equals(Object arg0) - { - return (arg0 != null) - && (((arg0 instanceof IntState) && (((IntState)arg0).value == value))); - } - - @Override - public int compareTo(IntState arg0) - { - if (arg0 == null) - throw new NullPointerException(); - - if (value > arg0.value) - return 1; - else if (value == arg0.value) - return 0; - else - return -1; - } - - /** - * @return the value - */ - public int getValue() - { - return value; - } - - /** - * @param value the value to set - */ - public void setValue(int value) - { - this.value = value; - } -} +package ecologylab.serialization.types.element; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + + +/** + * Reference version of an int type. Re-writable, unlike java.lang.Integer.

+ * Object wrapper for int primitive values. Useful for storing in HashMaps, and + * anywhere else that a reference type is needed. + */ +public class IntState extends ElementState implements Comparable +{ + private @simpl_scalar int value; + + public IntState(int b) + { + super(); + value = b; + } + + /** + * + */ + public IntState() + { + } + + /** + * Returns a hashcode for this Integer. + * + * @return a hash code value for this object. + * @since JDK1.0 + */ + @Override public int hashCode() + { + return value; + } + + @Override public String toString() + { + return "IntState[" + value + "]"; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override public boolean equals(Object arg0) + { + return (arg0 != null) + && (((arg0 instanceof IntState) && (((IntState)arg0).value == value))); + } + + @Override + public int compareTo(IntState arg0) + { + if (arg0 == null) + throw new NullPointerException(); + + if (value > arg0.value) + return 1; + else if (value == arg0.value) + return 0; + else + return -1; + } + + /** + * @return the value + */ + public int getValue() + { + return value; + } + + /** + * @param value the value to set + */ + public void setValue(int value) + { + this.value = value; + } +} diff --git a/simplCore/src/ecologylab/serialization/types/element/StringState.java b/simplCore/src/ecologylab/serialization/types/element/StringState.java index aeabbd54..92b977bc 100644 --- a/simplCore/src/ecologylab/serialization/types/element/StringState.java +++ b/simplCore/src/ecologylab/serialization/types/element/StringState.java @@ -1,36 +1,36 @@ -package ecologylab.serialization.types.element; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -public class StringState extends ElementState -{ - @simpl_scalar public String string; - - public StringState() - { - super(); - } - - public StringState(String string) - { - this.string = string; - } - - /** - * @return the string - */ - public String getString() - { - return string; - } - - /** - * @see ecologylab.generic.Debug#toString() - */ - @Override - public String toString() - { - return string; - } -} +package ecologylab.serialization.types.element; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +public class StringState extends ElementState +{ + @simpl_scalar public String string; + + public StringState() + { + super(); + } + + public StringState(String string) + { + this.string = string; + } + + /** + * @return the string + */ + public String getString() + { + return string; + } + + /** + * @see ecologylab.generic.Debug#toString() + */ + @Override + public String toString() + { + return string; + } +} diff --git a/simplCore/src/ecologylab/serialization/types/element/package.html b/simplCore/src/ecologylab/serialization/types/element/package.html index ddb58b7e..1566feea 100644 --- a/simplCore/src/ecologylab/serialization/types/element/package.html +++ b/simplCore/src/ecologylab/serialization/types/element/package.html @@ -1,4 +1,4 @@ - -Subclasses of ElementState that define nested XML elements. -These include single elements, collections, and maps. - + +Subclasses of ElementState that define nested XML elements. +These include single elements, collections, and maps. + diff --git a/simplCore/src/ecologylab/serialization/types/scalar/BinaryDataType.java b/simplCore/src/ecologylab/serialization/types/scalar/BinaryDataType.java index b5cc4f2c..44429acc 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/BinaryDataType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/BinaryDataType.java @@ -1,39 +1,39 @@ -package ecologylab.serialization.types.scalar; - -import java.nio.ByteBuffer; - -import ecologylab.generic.Base64Coder; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; -import ecologylab.serialization.types.ScalarType; - -@simpl_inherit -public class BinaryDataType extends ScalarType -implements CrossLanguageTypeConstants -{ - public BinaryDataType() - { - super(ByteBuffer.class, DOTNET_BINARY_DATA, null, null); - } - - /** - * read the Base64 encoded string . convert to byte array. - */ - @Override - public ByteBuffer getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - return ByteBuffer.wrap(Base64Coder.decode(value)); - } - - /** - * read the binary content of the input byteBuffer, and encode it using Base64 - */ - @Override - public String marshall(ByteBuffer input, TranslationContext serializationContext) - { - return new String(Base64Coder.encode(input.array())); - } -} +package ecologylab.serialization.types.scalar; + +import java.nio.ByteBuffer; + +import ecologylab.generic.Base64Coder; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; +import ecologylab.serialization.types.ScalarType; + +@simpl_inherit +public class BinaryDataType extends ScalarType +implements CrossLanguageTypeConstants +{ + public BinaryDataType() + { + super(ByteBuffer.class, DOTNET_BINARY_DATA, null, null); + } + + /** + * read the Base64 encoded string . convert to byte array. + */ + @Override + public ByteBuffer getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + return ByteBuffer.wrap(Base64Coder.decode(value)); + } + + /** + * read the binary content of the input byteBuffer, and encode it using Base64 + */ + @Override + public String marshall(ByteBuffer input, TranslationContext serializationContext) + { + return new String(Base64Coder.encode(input.array())); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/BooleanType.java b/simplCore/src/ecologylab/serialization/types/scalar/BooleanType.java index b82fe39e..20fdbe1f 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/BooleanType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/BooleanType.java @@ -1,203 +1,203 @@ -/* - * Created on Dec 31, 2004 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.io.IOException; -import java.lang.reflect.Field; - -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.CrossLanguageTypeConstants; -import ecologylab.serialization.types.ScalarType; - -/** - * Type system entry for boolean, a built-in primitive. - * - * @author andruid - */ -@simpl_inherit -public class BooleanType extends ScalarType implements CrossLanguageTypeConstants -{ - public static final boolean DEFAULT_VALUE = false; - - public static final String DEFAULT_VALUE_STRING = "false"; - - /** - * This constructor should only be called once per session, through a static initializer, - * typically in TypeRegistry. - *

- * To get the instance of this type object for use in translations, call - * TypeRegistry.get("boolean"). - * - */ - public BooleanType() - { - this(boolean.class); - } - - public BooleanType(Class thatClass) - { - super(thatClass, DOTNET_BOOLEAN, OBJC_BOOLEAN, null); - } - - /** - * Convert the parameter to boolean. - */ - public static boolean getValue(String valueString) - { - String lcValue = valueString.toLowerCase(); - return lcValue.equals("t") || lcValue.equals("true") || lcValue.equals("yes") - || (lcValue.equals("1")); - } - - /** - * If this is a reference type, build an appropriate Object, given a String - * representation. If it is a primitive type, return a boxed value. - * - * @param value - * String representation of the instance. - */ - @Override - public Boolean getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - return "null".equalsIgnoreCase(value) ? null : new Boolean(getValue(value)); - } - - /** - * This is a primitive type, so we set it specially. - * - * @see ecologylab.serialization.types.ScalarType#setField(java.lang.Object, - * java.lang.reflect.Field, java.lang.String) - */ - @Override - public boolean setField(Object object, Field field, String value) - { - boolean result = false; - try - { - field.setBoolean(object, getValue(value)); - result = true; - } - catch (Exception e) - { - setFieldError(field, value, e); - } - return result; - } - - /** - * The string representation for a Field of this type - */ - @Override - public String toString(Field field, Object object) - { - String result = "COULDN'T CONVERT!"; - try - { - result = Boolean.toString(field.getBoolean(object)); - } - catch (Exception e) - { - e.printStackTrace(); - } - return result; - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - * - * @param buffy - * @param field - * @param context - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) - throws IllegalArgumentException, IllegalAccessException - { - buffy.append(getValueToAppend(f2xo, context)); - } - - static final String TRUE = "true"; - - static final String FALSE = "false"; - - static final String SHORT_TRUE = "t"; - - static final String SHORT_FALSE = "f"; - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - * - * @param buffy - * @param context - * @param field - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, - TranslationContext serializationContext, Format format) throws IllegalArgumentException, - IllegalAccessException, IOException - { - buffy.append(getValueToAppend(fieldDescriptor, context)); - } - - public static String getValueToAppend(FieldDescriptor fieldDescriptor, Object context) - throws IllegalArgumentException, IllegalAccessException - { - String result = getNullStringIfNull(fieldDescriptor, context); - if (result == null) - { - boolean value = (Boolean) fieldDescriptor.getField().get(context); - - if (fieldDescriptor.getFormat() != null) - { - return (value ? SHORT_TRUE : SHORT_FALSE); - } - else - { - return (value ? TRUE : FALSE); - } - } - return result; - } - - /** - * The default value for this type, as a String. This value is the one that translateToXML(...) - * wont bother emitting. - * - * @return "false" - */ - @Override - public String defaultValueString() - { - return DEFAULT_VALUE_STRING; - } - - @Override - public Boolean defaultValue() - { - return DEFAULT_VALUE; - } - - /** - * True if the value in the Field object matches the default value for this type. - * - * @param field - * @return - */ - @Override - public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, - IllegalAccessException - { - return (Boolean) field.get(context) == DEFAULT_VALUE; - } - -} +/* + * Created on Dec 31, 2004 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; +import java.lang.reflect.Field; + +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.CrossLanguageTypeConstants; +import ecologylab.serialization.types.ScalarType; + +/** + * Type system entry for boolean, a built-in primitive. + * + * @author andruid + */ +@simpl_inherit +public class BooleanType extends ScalarType implements CrossLanguageTypeConstants +{ + public static final boolean DEFAULT_VALUE = false; + + public static final String DEFAULT_VALUE_STRING = "false"; + + /** + * This constructor should only be called once per session, through a static initializer, + * typically in TypeRegistry. + *

+ * To get the instance of this type object for use in translations, call + * TypeRegistry.get("boolean"). + * + */ + public BooleanType() + { + this(boolean.class); + } + + public BooleanType(Class thatClass) + { + super(thatClass, DOTNET_BOOLEAN, OBJC_BOOLEAN, null); + } + + /** + * Convert the parameter to boolean. + */ + public static boolean getValue(String valueString) + { + String lcValue = valueString.toLowerCase(); + return lcValue.equals("t") || lcValue.equals("true") || lcValue.equals("yes") + || (lcValue.equals("1")); + } + + /** + * If this is a reference type, build an appropriate Object, given a String + * representation. If it is a primitive type, return a boxed value. + * + * @param value + * String representation of the instance. + */ + @Override + public Boolean getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + return "null".equalsIgnoreCase(value) ? null : new Boolean(getValue(value)); + } + + /** + * This is a primitive type, so we set it specially. + * + * @see ecologylab.serialization.types.ScalarType#setField(java.lang.Object, + * java.lang.reflect.Field, java.lang.String) + */ + @Override + public boolean setField(Object object, Field field, String value) + { + boolean result = false; + try + { + field.setBoolean(object, getValue(value)); + result = true; + } + catch (Exception e) + { + setFieldError(field, value, e); + } + return result; + } + + /** + * The string representation for a Field of this type + */ + @Override + public String toString(Field field, Object object) + { + String result = "COULDN'T CONVERT!"; + try + { + result = Boolean.toString(field.getBoolean(object)); + } + catch (Exception e) + { + e.printStackTrace(); + } + return result; + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * + * @param buffy + * @param field + * @param context + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) + throws IllegalArgumentException, IllegalAccessException + { + buffy.append(getValueToAppend(f2xo, context)); + } + + static final String TRUE = "true"; + + static final String FALSE = "false"; + + static final String SHORT_TRUE = "t"; + + static final String SHORT_FALSE = "f"; + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * + * @param buffy + * @param context + * @param field + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, + TranslationContext serializationContext, Format format) throws IllegalArgumentException, + IllegalAccessException, IOException + { + buffy.append(getValueToAppend(fieldDescriptor, context)); + } + + public static String getValueToAppend(FieldDescriptor fieldDescriptor, Object context) + throws IllegalArgumentException, IllegalAccessException + { + String result = getNullStringIfNull(fieldDescriptor, context); + if (result == null) + { + boolean value = (Boolean) fieldDescriptor.getField().get(context); + + if (fieldDescriptor.getFormat() != null) + { + return (value ? SHORT_TRUE : SHORT_FALSE); + } + else + { + return (value ? TRUE : FALSE); + } + } + return result; + } + + /** + * The default value for this type, as a String. This value is the one that translateToXML(...) + * wont bother emitting. + * + * @return "false" + */ + @Override + public String defaultValueString() + { + return DEFAULT_VALUE_STRING; + } + + @Override + public Boolean defaultValue() + { + return DEFAULT_VALUE; + } + + /** + * True if the value in the Field object matches the default value for this type. + * + * @param field + * @return + */ + @Override + public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, + IllegalAccessException + { + return (Boolean) field.get(context) == DEFAULT_VALUE; + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ByteType.java b/simplCore/src/ecologylab/serialization/types/scalar/ByteType.java index b1223b06..1d73ad9a 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ByteType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ByteType.java @@ -1,171 +1,171 @@ -/* - * Created on Dec 31, 2004 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.io.IOException; -import java.lang.reflect.Field; - -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.CrossLanguageTypeConstants; -import ecologylab.serialization.types.ScalarType; - -/** - * Type system entry for byte, a built-in primitive. - * - * @author andruid - */ -@simpl_inherit -public class ByteType extends ScalarType -implements CrossLanguageTypeConstants -{ - public static final byte DEFAULT_VALUE = 0; - public static final String DEFAULT_VALUE_STRING = "0"; - -/** - * This constructor should only be called once per session, through - * a static initializer, typically in TypeRegistry. - *

- * To get the instance of this type object for use in translations, call - * TypeRegistry.get("byte"). - * - */ - public ByteType() - { - super(byte.class, DOTNET_BYTE, OBJC_BYTE, null); - } - - public ByteType(Class thatClass) - { - super(thatClass, DOTNET_BYTE, OBJC_BYTE, null); - } - - /** - * Convert the parameter to byte. - */ - public byte getValue(String valueString) - { - return Byte.parseByte(valueString); - } - - /** - * Parse the String into the (primitive) type, and return a boxed instance. - * - * @param value - * String representation of the instance. - */ - @Override - public Byte getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) - { - return new Byte(value); - } - - /** - * This is a primitive type, so we set it specially. - * - * @see ecologylab.serialization.types.ScalarType#setField(java.lang.Object, java.lang.reflect.Field, java.lang.String) - */ - @Override - public boolean setField(Object object, Field field, String value) - { - boolean result = false; - try - { - field.setByte(object, getValue(value)); - result = true; - } catch (Exception e) - { - setFieldError(field, value, e); - } - return result; - } -/** - * The string representation for a Field of this type - */ - @Override - public String toString(Field field, Object object) - { - String result = "COULDN'T CONVERT!"; - try - { - result = Byte.toString(field.getByte(object)); - } catch (Exception e) - { - e.printStackTrace(); - } - return result; - } - - /** - * The default value for this type, as a String. - * This value is the one that translateToXML(...) wont bother emitting. - * - * In this case, "false". - */ - @Override - public String defaultValueString() - { - return DEFAULT_VALUE_STRING; - } - - @Override - public Byte defaultValue() - { - return DEFAULT_VALUE; - } - - /** - * True if the value in the Field object matches the default value for this type. - * - * @param field - * @return - */ - @Override - public boolean isDefaultValue(Field field, Object context) - throws IllegalArgumentException, IllegalAccessException - { - return field.getByte(context) == DEFAULT_VALUE; - } - - /** - * Get the value from the Field, in the context. - * Append its value to the buffy. - * - * @param buffy - * @param field - * @param context - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) - throws IllegalArgumentException, IllegalAccessException - { - byte value = f2xo.getField().getByte(context); - - buffy.append(value); - } - - /** - * Get the value from the Field, in the context. - * Append its value to the buffy. - * - * @param buffy - * @param context - * @param field - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, TranslationContext serializationContext, Format format) - throws IllegalArgumentException, IllegalAccessException, IOException - { - byte value = fieldDescriptor.getField().getByte(context); - - buffy.append(Byte.toString(value)); - } -} +/* + * Created on Dec 31, 2004 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; +import java.lang.reflect.Field; + +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.CrossLanguageTypeConstants; +import ecologylab.serialization.types.ScalarType; + +/** + * Type system entry for byte, a built-in primitive. + * + * @author andruid + */ +@simpl_inherit +public class ByteType extends ScalarType +implements CrossLanguageTypeConstants +{ + public static final byte DEFAULT_VALUE = 0; + public static final String DEFAULT_VALUE_STRING = "0"; + +/** + * This constructor should only be called once per session, through + * a static initializer, typically in TypeRegistry. + *

+ * To get the instance of this type object for use in translations, call + * TypeRegistry.get("byte"). + * + */ + public ByteType() + { + super(byte.class, DOTNET_BYTE, OBJC_BYTE, null); + } + + public ByteType(Class thatClass) + { + super(thatClass, DOTNET_BYTE, OBJC_BYTE, null); + } + + /** + * Convert the parameter to byte. + */ + public byte getValue(String valueString) + { + return Byte.parseByte(valueString); + } + + /** + * Parse the String into the (primitive) type, and return a boxed instance. + * + * @param value + * String representation of the instance. + */ + @Override + public Byte getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) + { + return new Byte(value); + } + + /** + * This is a primitive type, so we set it specially. + * + * @see ecologylab.serialization.types.ScalarType#setField(java.lang.Object, java.lang.reflect.Field, java.lang.String) + */ + @Override + public boolean setField(Object object, Field field, String value) + { + boolean result = false; + try + { + field.setByte(object, getValue(value)); + result = true; + } catch (Exception e) + { + setFieldError(field, value, e); + } + return result; + } +/** + * The string representation for a Field of this type + */ + @Override + public String toString(Field field, Object object) + { + String result = "COULDN'T CONVERT!"; + try + { + result = Byte.toString(field.getByte(object)); + } catch (Exception e) + { + e.printStackTrace(); + } + return result; + } + + /** + * The default value for this type, as a String. + * This value is the one that translateToXML(...) wont bother emitting. + * + * In this case, "false". + */ + @Override + public String defaultValueString() + { + return DEFAULT_VALUE_STRING; + } + + @Override + public Byte defaultValue() + { + return DEFAULT_VALUE; + } + + /** + * True if the value in the Field object matches the default value for this type. + * + * @param field + * @return + */ + @Override + public boolean isDefaultValue(Field field, Object context) + throws IllegalArgumentException, IllegalAccessException + { + return field.getByte(context) == DEFAULT_VALUE; + } + + /** + * Get the value from the Field, in the context. + * Append its value to the buffy. + * + * @param buffy + * @param field + * @param context + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) + throws IllegalArgumentException, IllegalAccessException + { + byte value = f2xo.getField().getByte(context); + + buffy.append(value); + } + + /** + * Get the value from the Field, in the context. + * Append its value to the buffy. + * + * @param buffy + * @param context + * @param field + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, TranslationContext serializationContext, Format format) + throws IllegalArgumentException, IllegalAccessException, IOException + { + byte value = fieldDescriptor.getField().getByte(context); + + buffy.append(Byte.toString(value)); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/CharType.java b/simplCore/src/ecologylab/serialization/types/scalar/CharType.java index 32ffd2ac..dff93832 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/CharType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/CharType.java @@ -1,175 +1,175 @@ -/* - * Created on Dec 31, 2004 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.io.IOException; -import java.lang.reflect.Field; - -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.CrossLanguageTypeConstants; -import ecologylab.serialization.types.ScalarType; - -/** - * Type system entry for char, a built-in primitive. - * - * @author andruid - */ -@simpl_inherit -public class CharType extends ScalarType implements CrossLanguageTypeConstants -{ - public static final char DEFAULT_VALUE = ' '; - - public static final String DEFAULT_VALUE_STRING = " "; - - /** - * This constructor should only be called once per session, through a static initializer, - * typically in TypeRegistry. - *

- * To get the instance of this type object for use in translations, call - * TypeRegistry.get("char"). - * - */ - public CharType() - { - super(char.class, DOTNET_CHAR, OBJC_CHAR, null); - } - - public CharType(Class thatClass) - { - super(thatClass, DOTNET_CHAR, OBJC_CHAR, null); - } - - /** - * Convert the parameter to char. - */ - public char getValue(String valueString) - { - return valueString.charAt(0); - } - - /** - * Parse the String into the (primitive) type, and return a boxed instance. - * - * @param value - * String representation of the instance. - */ - @Override - public Character getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - return getValue(value); - } - - /** - * This is a primitive type, so we set it specially. - * - * @see ecologylab.serialization.types.ScalarType#setField(java.lang.Object, - * java.lang.reflect.Field, java.lang.String) - */ - @Override - public boolean setField(Object object, Field field, String value) - { - boolean result = false; - try - { - field.setChar(object, getValue(value)); - result = true; - } - catch (Exception e) - { - setFieldError(field, value, e); - } - return result; - } - - /** - * The string representation for a Field of this type - */ - @Override - public String toString(Field field, Object object) - { - String result = "COULDN'T CONVERT!"; - try - { - result = Character.toString(field.getChar(object)); - } - catch (Exception e) - { - e.printStackTrace(); - } - return result; - } - - /** - * The default value for this type, as a String. This value is the one that translateToXML(...) - * wont bother emitting. - * - * In this case, "false". - */ - @Override - public String defaultValueString() - { - return DEFAULT_VALUE_STRING; - } - - @Override - public Character defaultValue() - { - return DEFAULT_VALUE; - } - - /** - * True if the value in the Field object matches the default value for this type. - * - * @param field - * @return - */ - @Override - public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, - IllegalAccessException - { - return field.getChar(context) == DEFAULT_VALUE; - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - * - * @param buffy - * @param field - * @param context - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) - throws IllegalArgumentException, IllegalAccessException - { - char value = f2xo.getField().getChar(context); - - buffy.append(value); - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - * - * @param buffy - * @param context - * @param field - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, - TranslationContext serializationContext, Format format) throws IllegalArgumentException, - IllegalAccessException, IOException - { - char value = fieldDescriptor.getField().getChar(context); - - buffy.append(Character.toString(value)); - } -} +/* + * Created on Dec 31, 2004 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; +import java.lang.reflect.Field; + +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.CrossLanguageTypeConstants; +import ecologylab.serialization.types.ScalarType; + +/** + * Type system entry for char, a built-in primitive. + * + * @author andruid + */ +@simpl_inherit +public class CharType extends ScalarType implements CrossLanguageTypeConstants +{ + public static final char DEFAULT_VALUE = ' '; + + public static final String DEFAULT_VALUE_STRING = " "; + + /** + * This constructor should only be called once per session, through a static initializer, + * typically in TypeRegistry. + *

+ * To get the instance of this type object for use in translations, call + * TypeRegistry.get("char"). + * + */ + public CharType() + { + super(char.class, DOTNET_CHAR, OBJC_CHAR, null); + } + + public CharType(Class thatClass) + { + super(thatClass, DOTNET_CHAR, OBJC_CHAR, null); + } + + /** + * Convert the parameter to char. + */ + public char getValue(String valueString) + { + return valueString.charAt(0); + } + + /** + * Parse the String into the (primitive) type, and return a boxed instance. + * + * @param value + * String representation of the instance. + */ + @Override + public Character getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + return getValue(value); + } + + /** + * This is a primitive type, so we set it specially. + * + * @see ecologylab.serialization.types.ScalarType#setField(java.lang.Object, + * java.lang.reflect.Field, java.lang.String) + */ + @Override + public boolean setField(Object object, Field field, String value) + { + boolean result = false; + try + { + field.setChar(object, getValue(value)); + result = true; + } + catch (Exception e) + { + setFieldError(field, value, e); + } + return result; + } + + /** + * The string representation for a Field of this type + */ + @Override + public String toString(Field field, Object object) + { + String result = "COULDN'T CONVERT!"; + try + { + result = Character.toString(field.getChar(object)); + } + catch (Exception e) + { + e.printStackTrace(); + } + return result; + } + + /** + * The default value for this type, as a String. This value is the one that translateToXML(...) + * wont bother emitting. + * + * In this case, "false". + */ + @Override + public String defaultValueString() + { + return DEFAULT_VALUE_STRING; + } + + @Override + public Character defaultValue() + { + return DEFAULT_VALUE; + } + + /** + * True if the value in the Field object matches the default value for this type. + * + * @param field + * @return + */ + @Override + public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, + IllegalAccessException + { + return field.getChar(context) == DEFAULT_VALUE; + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * + * @param buffy + * @param field + * @param context + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) + throws IllegalArgumentException, IllegalAccessException + { + char value = f2xo.getField().getChar(context); + + buffy.append(value); + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * + * @param buffy + * @param context + * @param field + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, + TranslationContext serializationContext, Format format) throws IllegalArgumentException, + IllegalAccessException, IOException + { + char value = fieldDescriptor.getField().getChar(context); + + buffy.append(Character.toString(value)); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/CollectionTypeType.java b/simplCore/src/ecologylab/serialization/types/scalar/CollectionTypeType.java index 55c3b968..eecac53d 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/CollectionTypeType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/CollectionTypeType.java @@ -1,44 +1,44 @@ -/** - * - */ -package ecologylab.serialization.types.scalar; - -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CollectionType; -import ecologylab.serialization.types.TypeRegistry; - -/** - * @author andruid - * - */ -@simpl_inherit -public class CollectionTypeType extends ReferenceType -{ - public CollectionTypeType() - { - super(CollectionType.class, JAVA_SCALAR_TYPE, DOTNET_SCALAR_TYPE, OBJC_SCALAR_TYPE, null); - } - - /** - * Capitalize the value if it wasn't. - * Append "Type". - * Use this to call TypeRegistry.getType(). - */ - @Override - public CollectionType getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) - { - CollectionType result = TypeRegistry.getCollectionTypeByCrossPlatformName(value); - - return result; - } - - @Override - public String marshall(CollectionType instance, TranslationContext serializationContext) - { - String crossPlatformName = instance.getName(); - return crossPlatformName; - } - -} +/** + * + */ +package ecologylab.serialization.types.scalar; + +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CollectionType; +import ecologylab.serialization.types.TypeRegistry; + +/** + * @author andruid + * + */ +@simpl_inherit +public class CollectionTypeType extends ReferenceType +{ + public CollectionTypeType() + { + super(CollectionType.class, JAVA_SCALAR_TYPE, DOTNET_SCALAR_TYPE, OBJC_SCALAR_TYPE, null); + } + + /** + * Capitalize the value if it wasn't. + * Append "Type". + * Use this to call TypeRegistry.getType(). + */ + @Override + public CollectionType getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) + { + CollectionType result = TypeRegistry.getCollectionTypeByCrossPlatformName(value); + + return result; + } + + @Override + public String marshall(CollectionType instance, TranslationContext serializationContext) + { + String crossPlatformName = instance.getName(); + return crossPlatformName; + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/CompositeAsScalarType.java b/simplCore/src/ecologylab/serialization/types/scalar/CompositeAsScalarType.java index 2c8e87a2..15f31638 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/CompositeAsScalarType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/CompositeAsScalarType.java @@ -1,105 +1,105 @@ -package ecologylab.serialization.types.scalar; - -import java.io.IOException; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.ScalarType; - -/* - * This is not being used as composite are only treated as scalars in a certain context of serialization. for example bibtex - * but not in XML. - */ -@simpl_inherit -public class CompositeAsScalarType extends ScalarType -{ - public CompositeAsScalarType() - { - super((Class) CompositeAsScalarType.class, null, null, null); - } - - /** - * Append the String directly, unless it needs escaping, in which case, call escapeXML. - * - * @param instance - * @param buffy - * @param needsEscaping - */ - @Override - public void appendValue(T instance, StringBuilder buffy, boolean needsEscaping, TranslationContext serializationContext) - { - if(instance instanceof ElementState) - { - ClassDescriptor compositeElement = ClassDescriptor.getClassDescriptor(instance); - FieldDescriptor scalarValueFD = compositeElement.getScalarValueFieldDescripotor(); - if(scalarValueFD != null) - { - try - { - scalarValueFD.getScalarType().appendValue(buffy, scalarValueFD, instance); - } - catch (IllegalArgumentException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - catch (IllegalAccessException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - - } - /** - * Append the String directly, unless it needs escaping, in which case, call escapeXML. - * - * @param instance - * @param appendable - * @param needsEscaping - * @throws IOException - */ - @Override - public void appendValue(T instance, Appendable appendable, boolean needsEscaping, TranslationContext serializationContext, Format format) - throws IOException - { - if(instance instanceof ElementState) - { - ClassDescriptor compositeElement = ClassDescriptor.getClassDescriptor(instance); - FieldDescriptor scalarValueFD = compositeElement.getScalarValueFieldDescripotor(); - if(scalarValueFD != null) - { - try - { - scalarValueFD.getScalarType().appendValue(appendable, scalarValueFD, instance, null, format); - } - catch (IllegalArgumentException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - catch (IllegalAccessException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - } - - - @Override - public T getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - // TODO Auto-generated method stub - return null; - } - -} +package ecologylab.serialization.types.scalar; + +import java.io.IOException; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.ScalarType; + +/* + * This is not being used as composite are only treated as scalars in a certain context of serialization. for example bibtex + * but not in XML. + */ +@simpl_inherit +public class CompositeAsScalarType extends ScalarType +{ + public CompositeAsScalarType() + { + super((Class) CompositeAsScalarType.class, null, null, null); + } + + /** + * Append the String directly, unless it needs escaping, in which case, call escapeXML. + * + * @param instance + * @param buffy + * @param needsEscaping + */ + @Override + public void appendValue(T instance, StringBuilder buffy, boolean needsEscaping, TranslationContext serializationContext) + { + if(instance instanceof ElementState) + { + ClassDescriptor compositeElement = ClassDescriptor.getClassDescriptor(instance); + FieldDescriptor scalarValueFD = compositeElement.getScalarValueFieldDescripotor(); + if(scalarValueFD != null) + { + try + { + scalarValueFD.getScalarType().appendValue(buffy, scalarValueFD, instance); + } + catch (IllegalArgumentException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + catch (IllegalAccessException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + } + /** + * Append the String directly, unless it needs escaping, in which case, call escapeXML. + * + * @param instance + * @param appendable + * @param needsEscaping + * @throws IOException + */ + @Override + public void appendValue(T instance, Appendable appendable, boolean needsEscaping, TranslationContext serializationContext, Format format) + throws IOException + { + if(instance instanceof ElementState) + { + ClassDescriptor compositeElement = ClassDescriptor.getClassDescriptor(instance); + FieldDescriptor scalarValueFD = compositeElement.getScalarValueFieldDescripotor(); + if(scalarValueFD != null) + { + try + { + scalarValueFD.getScalarType().appendValue(appendable, scalarValueFD, instance, null, format); + } + catch (IllegalArgumentException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + catch (IllegalAccessException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } + + + @Override + public T getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/DateType.java b/simplCore/src/ecologylab/serialization/types/scalar/DateType.java index 043f2c42..66496822 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/DateType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/DateType.java @@ -1,88 +1,88 @@ -/* - * Created on Jan 2, 2005 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; - -/** - * Type system entry for {@link java.util.Date Date}. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -@simpl_inherit -public class DateType extends ReferenceType implements CrossLanguageTypeConstants -{ - static final String datePatterns[] = - { - "EEE MMM dd kk:mm:ss zzz yyyy", - "yyyy:MM:dd HH:mm:ss", - "yyyy:MM:dd HH:mm", - "yyyy-MM-dd HH:mm:ss", - "yyyy-MM-dd HH:mm", - "MMM dd, yyyy", - "yyyyMMdd", - "MM/dd/yyyy", - "MM/dd/yyyy K:mm aa", - }; - static final DateFormat dateFormats[] = new DateFormat[datePatterns.length + 1]; - - static final DateFormat plainDf = DateFormat.getDateTimeInstance(); - - static - { - for (int i=0; i< datePatterns.length; i++) - dateFormats[i] = new SimpleDateFormat(datePatterns[i]); - dateFormats[datePatterns.length] = plainDf; - } - - public DateType() - { - super(Date.class, JAVA_DATE, DOTNET_DATE, OBJC_DATE, null); - } - - /** - * @param value - * is interpreted as a SimpleDateFormat in the form EEE MMM dd kk:mm:ss zzz yyyy (for - * example Wed Aug 02 13:12:50 CDT 2006); if that does not work, then attempts to use the - * DateFormat for the current locale instead. - * - * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], - * ScalarUnmarshallingContext) - */ - @Override - public Date getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - for (DateFormat dateFormatParser: dateFormats) - { - try - { - return dateFormatParser.parse(value); - } catch (java.text.ParseException ex) - { - // simply try the next pattern - } - if (formatStrings != null) - for (String thatFormat: formatStrings) - { - try - { - return new SimpleDateFormat(thatFormat).parse(value); - } catch (java.text.ParseException ex) - { - // simply try the next pattern - } - - } - } - error("Failed to parse date: " + value); - return null; - } -} +/* + * Created on Jan 2, 2005 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +/** + * Type system entry for {@link java.util.Date Date}. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +@simpl_inherit +public class DateType extends ReferenceType implements CrossLanguageTypeConstants +{ + static final String datePatterns[] = + { + "EEE MMM dd kk:mm:ss zzz yyyy", + "yyyy:MM:dd HH:mm:ss", + "yyyy:MM:dd HH:mm", + "yyyy-MM-dd HH:mm:ss", + "yyyy-MM-dd HH:mm", + "MMM dd, yyyy", + "yyyyMMdd", + "MM/dd/yyyy", + "MM/dd/yyyy K:mm aa", + }; + static final DateFormat dateFormats[] = new DateFormat[datePatterns.length + 1]; + + static final DateFormat plainDf = DateFormat.getDateTimeInstance(); + + static + { + for (int i=0; i< datePatterns.length; i++) + dateFormats[i] = new SimpleDateFormat(datePatterns[i]); + dateFormats[datePatterns.length] = plainDf; + } + + public DateType() + { + super(Date.class, JAVA_DATE, DOTNET_DATE, OBJC_DATE, null); + } + + /** + * @param value + * is interpreted as a SimpleDateFormat in the form EEE MMM dd kk:mm:ss zzz yyyy (for + * example Wed Aug 02 13:12:50 CDT 2006); if that does not work, then attempts to use the + * DateFormat for the current locale instead. + * + * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], + * ScalarUnmarshallingContext) + */ + @Override + public Date getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + for (DateFormat dateFormatParser: dateFormats) + { + try + { + return dateFormatParser.parse(value); + } catch (java.text.ParseException ex) + { + // simply try the next pattern + } + if (formatStrings != null) + for (String thatFormat: formatStrings) + { + try + { + return new SimpleDateFormat(thatFormat).parse(value); + } catch (java.text.ParseException ex) + { + // simply try the next pattern + } + + } + } + error("Failed to parse date: " + value); + return null; + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/DoubleType.java b/simplCore/src/ecologylab/serialization/types/scalar/DoubleType.java index 9e18c0ab..ef57afee 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/DoubleType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/DoubleType.java @@ -1,245 +1,246 @@ -/* - * Created on Dec 31, 2004 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.HashMap; - -import ecologylab.generic.text.EfficientDecimalFormat; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.CrossLanguageTypeConstants; -import ecologylab.serialization.types.ScalarType; - -/** - * Type system entry for double, a built-in primitive. - * - * @author andruid - */ -@simpl_inherit -public class DoubleType extends ScalarType implements CrossLanguageTypeConstants -{ - public static final double DEFAULT_VALUE = 0; - - public static final String DEFAULT_VALUE_STRING = "0.0"; - - /** The map of format Strings to their associated decimal formats. */ - private static final HashMap formatMap = new HashMap(); - - /** - * This constructor should only be called once per session, through a static initializer, - * typically in TypeRegistry. - *

- * To get the instance of this type object for use in translations, call - * TypeRegistry.get("double"). - * - */ - public DoubleType() - { - this(double.class); - } - - public DoubleType(Class thatClass) - { - super(thatClass, DOTNET_DOUBLE, OBJC_DOUBLE, null); - } - - /** - * Convert the parameter to double. - */ - public double getValue(String valueString) - { - return Double.parseDouble(valueString); - } - - /** - * Parse the String into the (primitive) type, and return a boxed instance. - * - * @param value - * String representation of the instance. - */ - @Override - public Double getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - return "null".equalsIgnoreCase(value) ? null : (value != null && value.contains("/")) ? rationalToDouble(value) : new Double(value); - } - - public static double rationalToDouble(String rationalString) - { - String[] stringD = rationalString.split("/", 2); - double d0 = Double.parseDouble(stringD[0]); - double d1 = Double.parseDouble(stringD[1]); - - return d0 / d1; - } - - /** - * This is a primitive type, so we set it specially. - * - * @see ecologylab.serialization.types.ScalarType#setField(Object, Field, String) - */ - @Override - public boolean setField(Object object, Field field, String value) - { - boolean result = false; - try - { - field.setDouble(object, getValue(value)); - result = true; - } - catch (Exception e) - { - setFieldError(field, value, e); - } - return result; - } - - /** - * The string representation for a Field of this type - */ - @Override - public String toString(Field field, Object context) - { - String result = "COULDN'T CONVERT!"; - try - { - result = Double.toString((Double) field.get(context)); - } - catch (Exception e) - { - e.printStackTrace(); - } - return result; - } - - /** - * The default value for this type, as a String. This value is the one that translateToXML(...) - * wont bother emitting. - * - * @return "0" - */ - @Override - public String defaultValueString() - { - return DEFAULT_VALUE_STRING; - } - - /** - * Since DoubleType is a floating point value, returns true. - * - * @return true - */ - @Override - public boolean isFloatingPoint() - { - return true; - } - - /** - * True if the value in the Field object matches the default value for this type. - * - * @param field - * @return - */ - @Override - public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, - IllegalAccessException - { - return (Double) field.get(context) == DEFAULT_VALUE; - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - * - * @param buffy - * @param field - * @param context - * @param formatStrings - * an array of 0 or 1 items containing a pattern String that specifies how the value will - * be emitted. Patterns are specified using {@link java.text.DecimalFormat}. - * @throws IllegalAccessException - * @throws IllegalArgumentException - * @see java.text.DecimalFormat - */ - @Override - public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) - throws IllegalArgumentException, IllegalAccessException - { - buffy.append(getValueToAppend(f2xo, context)); - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - * - * @param buffy - * @param context - * @param field - * @throws IllegalAccessException - * @throws IllegalArgumentException - * @throws IOException - */ - @Override - public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, - TranslationContext serializationContext, Format format) throws IllegalArgumentException, - IllegalAccessException, IOException - { - buffy.append(getValueToAppend(fieldDescriptor, context)); - } - - public static String getValueToAppend(FieldDescriptor fieldDescriptor, Object context) - throws IllegalArgumentException, IllegalAccessException - { - if (fieldDescriptor.getField() == null || fieldDescriptor.getField().get(context) == null) - return "null"; - - double value = (Double) fieldDescriptor.getField().get(context); - String[] formatStrings = fieldDescriptor.getFormat(); - StringBuilder res = new StringBuilder(); - - if (formatStrings != null) - { - EfficientDecimalFormat decFormat = getFormat(formatStrings[0]); - - try - { - decFormat.format(value, res); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - else - { - res.append(Double.toString(value)); - } - return res.toString(); - } - - private static EfficientDecimalFormat getFormat(String formatString) - { - EfficientDecimalFormat decFormat = formatMap.get(formatString); - - if (decFormat == null) - { - synchronized (formatMap) - { - decFormat = formatMap.get(formatString); - - if (decFormat == null) - { - decFormat = new EfficientDecimalFormat(formatString); - formatMap.put(formatString, decFormat); - } - } - } - - return decFormat; - } -} +/* + * Created on Dec 31, 2004 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashMap; + +import ecologylab.generic.text.EfficientDecimalFormat; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.CrossLanguageTypeConstants; +import ecologylab.serialization.types.ScalarType; + +/** + * Type system entry for double, a built-in primitive. + * + * @author andruid + */ +@simpl_inherit +public class DoubleType extends ScalarType implements CrossLanguageTypeConstants +{ + public static final double DEFAULT_VALUE = 0; + + public static final String DEFAULT_VALUE_STRING = "0.0"; + + /** The map of format Strings to their associated decimal formats. */ + private static final HashMap formatMap = new HashMap(); + + /** + * This constructor should only be called once per session, through a static initializer, + * typically in TypeRegistry. + *

+ * To get the instance of this type object for use in translations, call + * TypeRegistry.get("double"). + * + */ + public DoubleType() + { + this(double.class); + } + + public DoubleType(Class thatClass) + { + super(thatClass, DOTNET_DOUBLE, OBJC_DOUBLE, null); + needJsonSerializationQuotation = false; + } + + /** + * Convert the parameter to double. + */ + public double getValue(String valueString) + { + return Double.parseDouble(valueString); + } + + /** + * Parse the String into the (primitive) type, and return a boxed instance. + * + * @param value + * String representation of the instance. + */ + @Override + public Double getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + return "null".equalsIgnoreCase(value) ? null : (value != null && value.contains("/")) ? rationalToDouble(value) : new Double(value); + } + + public static double rationalToDouble(String rationalString) + { + String[] stringD = rationalString.split("/", 2); + double d0 = Double.parseDouble(stringD[0]); + double d1 = Double.parseDouble(stringD[1]); + + return d0 / d1; + } + + /** + * This is a primitive type, so we set it specially. + * + * @see ecologylab.serialization.types.ScalarType#setField(Object, Field, String) + */ + @Override + public boolean setField(Object object, Field field, String value) + { + boolean result = false; + try + { + field.setDouble(object, getValue(value)); + result = true; + } + catch (Exception e) + { + setFieldError(field, value, e); + } + return result; + } + + /** + * The string representation for a Field of this type + */ + @Override + public String toString(Field field, Object context) + { + String result = "COULDN'T CONVERT!"; + try + { + result = Double.toString((Double) field.get(context)); + } + catch (Exception e) + { + e.printStackTrace(); + } + return result; + } + + /** + * The default value for this type, as a String. This value is the one that translateToXML(...) + * wont bother emitting. + * + * @return "0" + */ + @Override + public String defaultValueString() + { + return DEFAULT_VALUE_STRING; + } + + /** + * Since DoubleType is a floating point value, returns true. + * + * @return true + */ + @Override + public boolean isFloatingPoint() + { + return true; + } + + /** + * True if the value in the Field object matches the default value for this type. + * + * @param field + * @return + */ + @Override + public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, + IllegalAccessException + { + return (Double) field.get(context) == DEFAULT_VALUE; + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * + * @param buffy + * @param field + * @param context + * @param formatStrings + * an array of 0 or 1 items containing a pattern String that specifies how the value will + * be emitted. Patterns are specified using {@link java.text.DecimalFormat}. + * @throws IllegalAccessException + * @throws IllegalArgumentException + * @see java.text.DecimalFormat + */ + @Override + public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) + throws IllegalArgumentException, IllegalAccessException + { + buffy.append(getValueToAppend(f2xo, context)); + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * + * @param buffy + * @param context + * @param field + * @throws IllegalAccessException + * @throws IllegalArgumentException + * @throws IOException + */ + @Override + public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, + TranslationContext serializationContext, Format format) throws IllegalArgumentException, + IllegalAccessException, IOException + { + buffy.append(getValueToAppend(fieldDescriptor, context)); + } + + public static String getValueToAppend(FieldDescriptor fieldDescriptor, Object context) + throws IllegalArgumentException, IllegalAccessException + { + if (fieldDescriptor.getField() == null || fieldDescriptor.getField().get(context) == null) + return "null"; + + double value = (Double) fieldDescriptor.getField().get(context); + String[] formatStrings = fieldDescriptor.getFormat(); + StringBuilder res = new StringBuilder(); + + if (formatStrings != null) + { + EfficientDecimalFormat decFormat = getFormat(formatStrings[0]); + + try + { + decFormat.format(value, res); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + else + { + res.append(Double.toString(value)); + } + return res.toString(); + } + + private static EfficientDecimalFormat getFormat(String formatString) + { + EfficientDecimalFormat decFormat = formatMap.get(formatString); + + if (decFormat == null) + { + synchronized (formatMap) + { + decFormat = formatMap.get(formatString); + + if (decFormat == null) + { + decFormat = new EfficientDecimalFormat(formatString); + formatMap.put(formatString, decFormat); + } + } + } + + return decFormat; + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/EnumeratedType.java b/simplCore/src/ecologylab/serialization/types/scalar/EnumeratedType.java index e4fc9804..164019ec 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/EnumeratedType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/EnumeratedType.java @@ -1,85 +1,85 @@ -package ecologylab.serialization.types.scalar; - -import java.lang.reflect.Field; -import java.util.ArrayList; - -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_nowrap; - -public class EnumeratedType extends ReferenceType -{ - @simpl_nowrap - @simpl_collection("enum_string_constants") - ArrayList enumStringConstants = new ArrayList(); - - String enumTypeSimpleName = ""; - - public EnumeratedType() - { - super(Enum.class, null, null, null, null); - } - - public EnumeratedType(Field field) - { - if (field.getType().isEnum()) - { - Object[] enumArray = field.getType().getEnumConstants(); - for (Object enumObj : enumArray) - { - if (enumObj instanceof Enum) - { - Enum enumeratedType = ((Enum) enumObj); - enumStringConstants.add(enumeratedType.toString()); - } - } - } - - enumTypeSimpleName = field.getType().getSimpleName(); - } - - @Override - public boolean setField(Object context, Field field, String valueString, String[] format, ScalarUnmarshallingContext scalarUnmarshallingContext) - { - if (valueString == null) - return true; - - boolean result = false; - Enum referenceObject; - - try - { - referenceObject = XMLTools.createEnumeratedType(field, valueString); - if (referenceObject != null) - { - field.set(context, referenceObject); - result = true; - } - } - catch (Exception e) - { - setFieldError(field, valueString, e); - } - return result; - } - - @Override - public String getSimpleName() - { - return enumTypeSimpleName; - } - - public ArrayList getEnumStringConstants() - { - return enumStringConstants; - } - - @Override - public Enum getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - // TODO Auto-generated method stub - return null; - } -} +package ecologylab.serialization.types.scalar; + +import java.lang.reflect.Field; +import java.util.ArrayList; + +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_nowrap; + +public class EnumeratedType extends ReferenceType +{ + @simpl_nowrap + @simpl_collection("enum_string_constants") + ArrayList enumStringConstants = new ArrayList(); + + String enumTypeSimpleName = ""; + + public EnumeratedType() + { + super(Enum.class, null, null, null, null); + } + + public EnumeratedType(Field field) + { + if (field.getType().isEnum()) + { + Object[] enumArray = field.getType().getEnumConstants(); + for (Object enumObj : enumArray) + { + if (enumObj instanceof Enum) + { + Enum enumeratedType = ((Enum) enumObj); + enumStringConstants.add(enumeratedType.toString()); + } + } + } + + enumTypeSimpleName = field.getType().getSimpleName(); + } + + @Override + public boolean setField(Object context, Field field, String valueString, String[] format, ScalarUnmarshallingContext scalarUnmarshallingContext) + { + if (valueString == null) + return true; + + boolean result = false; + Enum referenceObject; + + try + { + referenceObject = XMLTools.createEnumeratedType(field, valueString); + if (referenceObject != null) + { + field.set(context, referenceObject); + result = true; + } + } + catch (Exception e) + { + setFieldError(field, valueString, e); + } + return result; + } + + @Override + public String getSimpleName() + { + return enumTypeSimpleName; + } + + public ArrayList getEnumStringConstants() + { + return enumStringConstants; + } + + @Override + public Enum getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + // TODO Auto-generated method stub + return null; + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/FileType.java b/simplCore/src/ecologylab/serialization/types/scalar/FileType.java index 7d997734..b8c51bd6 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/FileType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/FileType.java @@ -1,66 +1,66 @@ -/* - * Created on Dec 22, 2006 - */ -package ecologylab.serialization.types.scalar; - -import java.io.File; -import java.io.IOException; - -import ecologylab.generic.StringTools; -import ecologylab.io.Files; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -@simpl_inherit -public class FileType extends ReferenceType implements CrossLanguageTypeConstants -{ - - /** - */ - public FileType() - { - super(File.class, JAVA_FILE, DOTNET_FILE, OBJC_FILE, null); - } - - @Override - public File getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - File fileContext = (scalarUnmarshallingContext == null) ? null : scalarUnmarshallingContext - .fileContext(); - File file = (fileContext == null) ? new File(value) : new File(fileContext, value); - try - { - return file.getCanonicalFile(); - } - catch (IOException e) - { - e.printStackTrace(); - return file; - } - } - - @Override - public String marshall(File instance, TranslationContext serializationContext) - { - File contextualizedInstance = instance; - if (serializationContext != null) - { - File fileContext = serializationContext.fileContext(); - if (fileContext != null) - { - String pathRelativeTo = StringTools.getPathRelativeTo(instance.getAbsolutePath(), - fileContext.getAbsolutePath(), Files.sep); - if (pathRelativeTo != null) - return pathRelativeTo; - } - } - - return super.marshall(contextualizedInstance, serializationContext); - } -} +/* + * Created on Dec 22, 2006 + */ +package ecologylab.serialization.types.scalar; + +import java.io.File; +import java.io.IOException; + +import ecologylab.generic.StringTools; +import ecologylab.io.Files; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +@simpl_inherit +public class FileType extends ReferenceType implements CrossLanguageTypeConstants +{ + + /** + */ + public FileType() + { + super(File.class, JAVA_FILE, DOTNET_FILE, OBJC_FILE, null); + } + + @Override + public File getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + File fileContext = (scalarUnmarshallingContext == null) ? null : scalarUnmarshallingContext + .fileContext(); + File file = (fileContext == null) ? new File(value) : new File(fileContext, value); + try + { + return file.getCanonicalFile(); + } + catch (IOException e) + { + e.printStackTrace(); + return file; + } + } + + @Override + public String marshall(File instance, TranslationContext serializationContext) + { + File contextualizedInstance = instance; + if (serializationContext != null) + { + File fileContext = serializationContext.fileContext(); + if (fileContext != null) + { + String pathRelativeTo = StringTools.getPathRelativeTo(instance.getAbsolutePath(), + fileContext.getAbsolutePath(), Files.sep); + if (pathRelativeTo != null) + return pathRelativeTo; + } + } + + return super.marshall(contextualizedInstance, serializationContext); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/FloatType.java b/simplCore/src/ecologylab/serialization/types/scalar/FloatType.java index db955a1f..644ad3db 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/FloatType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/FloatType.java @@ -1,192 +1,193 @@ -/* - * Created on Dec 31, 2004 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.io.IOException; -import java.lang.reflect.Field; - -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.CrossLanguageTypeConstants; -import ecologylab.serialization.types.ScalarType; - -/** - * Type system entry for float, a built-in primitive. - * - * @author andruid - */ -@simpl_inherit -public class FloatType extends ScalarType -implements CrossLanguageTypeConstants -{ - public static final float DEFAULT_VALUE = 0; - - public static final String DEFAULT_VALUE_STRING = "0"; - - /** - * This constructor should only be called once per session, through a static initializer, - * typically in TypeRegistry. - *

- * To get the instance of this type object for use in translations, call - * TypeRegistry.get("float"). - * - */ - public FloatType() - { - this(float.class); - } - - public FloatType(Class thatClass) - { - super(thatClass, DOTNET_FLOAT, OBJC_FLOAT, null); - } - - /** - * Convert the parameter to float. - */ - public float getValue(String valueString) - { - return Float.parseFloat(valueString); - } - - /** - * If this is a reference type, build an appropriate Object, given a String - * representation. If it is a primitive type, return a boxed value. - * - * @param value - * String representation of the instance. - */ - @Override - public Float getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - return "null".equalsIgnoreCase(value) ? null : (value != null && value.contains("/")) ? (float) DoubleType.rationalToDouble(value) : getValue(value); - } - - /** - * This is a primitive type, so we set it specially. - * - * @see ecologylab.serialization.types.ScalarType#setField(Object, Field, String) - */ - @Override - public boolean setField(Object object, Field field, String value) - { - boolean result = false; - try - { - field.setFloat(object, getValue(value)); - result = true; - } - catch (Exception e) - { - setFieldError(field, value, e); - } - return result; - } - - /** - * The string representation for a Field of this type - */ - @Override - public String toString(Field field, Object context) - { - String result = "COULDN'T CONVERT!"; - try - { - result = Float.toString(field.getFloat(context)); - } - catch (Exception e) - { - e.printStackTrace(); - } - return result; - } - - /** - * The default value for this type, as a String. This value is the one that translateToXML(...) - * wont bother emitting. - * - * @return "0" - */ - @Override - public String defaultValueString() - { - return DEFAULT_VALUE_STRING; - } - - @Override - public Float defaultValue() - { - return DEFAULT_VALUE; - } - - /** - * Since FloatType is a floating point value, returns true. - * - * @return true - */ - @Override - public boolean isFloatingPoint() - { - return true; - } - - /** - * True if the value in the Field object matches the default value for this type. - * - * @param field - * @return - */ - @Override - public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, - IllegalAccessException - { - return (Float) field.get(context) == DEFAULT_VALUE; - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - * - * @param buffy - * @param field - * @param context - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) - throws IllegalArgumentException, IllegalAccessException - { - buffy.append(getValueToAppend(f2xo, context)); - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - * - * @param buffy - * @param context - * @param field - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, TranslationContext serializationContext, Format format) - throws IllegalArgumentException, IllegalAccessException, IOException - { - buffy.append(getValueToAppend(fieldDescriptor, context)); - } - - public static String getValueToAppend(FieldDescriptor fieldDescriptor, Object context) - throws IllegalArgumentException, IllegalAccessException - { - String result = getNullStringIfNull(fieldDescriptor, context); - if (result == null) - result = fieldDescriptor.getField().get(context).toString(); - return result; - } - -} +/* + * Created on Dec 31, 2004 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; +import java.lang.reflect.Field; + +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.CrossLanguageTypeConstants; +import ecologylab.serialization.types.ScalarType; + +/** + * Type system entry for float, a built-in primitive. + * + * @author andruid + */ +@simpl_inherit +public class FloatType extends ScalarType +implements CrossLanguageTypeConstants +{ + public static final float DEFAULT_VALUE = 0; + + public static final String DEFAULT_VALUE_STRING = "0"; + + /** + * This constructor should only be called once per session, through a static initializer, + * typically in TypeRegistry. + *

+ * To get the instance of this type object for use in translations, call + * TypeRegistry.get("float"). + * + */ + public FloatType() + { + this(float.class); + } + + public FloatType(Class thatClass) + { + super(thatClass, DOTNET_FLOAT, OBJC_FLOAT, null); + needJsonSerializationQuotation = false; + } + + /** + * Convert the parameter to float. + */ + public float getValue(String valueString) + { + return Float.parseFloat(valueString); + } + + /** + * If this is a reference type, build an appropriate Object, given a String + * representation. If it is a primitive type, return a boxed value. + * + * @param value + * String representation of the instance. + */ + @Override + public Float getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + return "null".equalsIgnoreCase(value) ? null : (value != null && value.contains("/")) ? (float) DoubleType.rationalToDouble(value) : getValue(value); + } + + /** + * This is a primitive type, so we set it specially. + * + * @see ecologylab.serialization.types.ScalarType#setField(Object, Field, String) + */ + @Override + public boolean setField(Object object, Field field, String value) + { + boolean result = false; + try + { + field.setFloat(object, getValue(value)); + result = true; + } + catch (Exception e) + { + setFieldError(field, value, e); + } + return result; + } + + /** + * The string representation for a Field of this type + */ + @Override + public String toString(Field field, Object context) + { + String result = "COULDN'T CONVERT!"; + try + { + result = Float.toString(field.getFloat(context)); + } + catch (Exception e) + { + e.printStackTrace(); + } + return result; + } + + /** + * The default value for this type, as a String. This value is the one that translateToXML(...) + * wont bother emitting. + * + * @return "0" + */ + @Override + public String defaultValueString() + { + return DEFAULT_VALUE_STRING; + } + + @Override + public Float defaultValue() + { + return DEFAULT_VALUE; + } + + /** + * Since FloatType is a floating point value, returns true. + * + * @return true + */ + @Override + public boolean isFloatingPoint() + { + return true; + } + + /** + * True if the value in the Field object matches the default value for this type. + * + * @param field + * @return + */ + @Override + public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, + IllegalAccessException + { + return (Float) field.get(context) == DEFAULT_VALUE; + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * + * @param buffy + * @param field + * @param context + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) + throws IllegalArgumentException, IllegalAccessException + { + buffy.append(getValueToAppend(f2xo, context)); + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * + * @param buffy + * @param context + * @param field + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, TranslationContext serializationContext, Format format) + throws IllegalArgumentException, IllegalAccessException, IOException + { + buffy.append(getValueToAppend(fieldDescriptor, context)); + } + + public static String getValueToAppend(FieldDescriptor fieldDescriptor, Object context) + throws IllegalArgumentException, IllegalAccessException + { + String result = getNullStringIfNull(fieldDescriptor, context); + if (result == null) + result = fieldDescriptor.getField().get(context).toString(); + return result; + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ImageType.java b/simplCore/src/ecologylab/serialization/types/scalar/ImageType.java index b313ebc4..05304df8 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ImageType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ImageType.java @@ -1,68 +1,68 @@ -package ecologylab.serialization.types.scalar; - -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.types.ScalarType; - -public abstract class ImageType extends ScalarType - -{ - public ImageType(Class thatClass) - { - super(thatClass); - } - - /** - * get platform dependent image type T instance from string. - */ - @Override - public abstract T getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext); - - /** - * marshall platform dependent image type T to string. - */ - @Override - public abstract String marshall(T input, TranslationContext serializationContext); - - /** - * convert raw image byte array to string - * - * @param imageRawByte - * @return - */ - public String byteArrayToString(byte[] rawImageByteArray) - { - StringBuilder res = new StringBuilder(rawImageByteArray.length*2); - - for (int i = 0; i < rawImageByteArray.length; ++i) - { - int in = (rawImageByteArray[i] >= 0)?rawImageByteArray[i]:256+rawImageByteArray[i]; - String x = Integer.toString(in,16); - if (in < 16) - res.append("0"); - res.append(x); - } - - return res.toString(); - } - - /** - * convert serialized image string to byte array - * - * @param serializedImageString - * @return - */ - public byte[] stringToByteArray(String serializedImageString) - { - serializedImageString = serializedImageString.trim(); - byte[] data = new byte[serializedImageString.length() / 2]; - - // TODO: optimize - for (int i = 0; i < data.length; ++i) - data[i] = (byte) Integer.parseInt(serializedImageString.substring(2 * i, 2 * i + 2), 16); - - return data; - } - -} +package ecologylab.serialization.types.scalar; + +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.types.ScalarType; + +public abstract class ImageType extends ScalarType + +{ + public ImageType(Class thatClass) + { + super(thatClass); + } + + /** + * get platform dependent image type T instance from string. + */ + @Override + public abstract T getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext); + + /** + * marshall platform dependent image type T to string. + */ + @Override + public abstract String marshall(T input, TranslationContext serializationContext); + + /** + * convert raw image byte array to string + * + * @param imageRawByte + * @return + */ + public String byteArrayToString(byte[] rawImageByteArray) + { + StringBuilder res = new StringBuilder(rawImageByteArray.length*2); + + for (int i = 0; i < rawImageByteArray.length; ++i) + { + int in = (rawImageByteArray[i] >= 0)?rawImageByteArray[i]:256+rawImageByteArray[i]; + String x = Integer.toString(in,16); + if (in < 16) + res.append("0"); + res.append(x); + } + + return res.toString(); + } + + /** + * convert serialized image string to byte array + * + * @param serializedImageString + * @return + */ + public byte[] stringToByteArray(String serializedImageString) + { + serializedImageString = serializedImageString.trim(); + byte[] data = new byte[serializedImageString.length() / 2]; + + // TODO: optimize + for (int i = 0; i < data.length; ++i) + data[i] = (byte) Integer.parseInt(serializedImageString.substring(2 * i, 2 * i + 2), 16); + + return data; + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/IntType.java b/simplCore/src/ecologylab/serialization/types/scalar/IntType.java index 0898879e..98b4df72 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/IntType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/IntType.java @@ -1,185 +1,186 @@ -/* - * Created on Dec 31, 2004 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.io.IOException; -import java.lang.reflect.Field; - -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.CrossLanguageTypeConstants; -import ecologylab.serialization.types.ScalarType; - -/** - * Type system entry for int, a built-in primitive. - * - * @author andruid - */ -@simpl_inherit -public class IntType extends ScalarType implements CrossLanguageTypeConstants -{ - public static final int DEFAULT_VALUE = new Integer(0); - - public static final String DEFAULT_VALUE_STRING = "0"; - - /** - * This constructor should only be called once per session, through a static initializer, - * typically in TypeRegistry. - *

- * To get the instance of this type object for use in translations, call - * TypeRegistry.get("int"). - * - */ - public IntType() - { - this(int.class); - } - - public IntType(Class thatClass) - { - super(thatClass, DOTNET_INTEGER, OBJC_INTEGER, null); - } - - /** - * Convert the parameter to int. - */ - public int getValue(String valueString) - { - return Integer.parseInt(valueString); - } - - /** - * If this is a reference type, build an appropriate Object, given a String - * representation. If it is a primitive type, return a boxed value. - * - * @param value - * String representation of the instance. - */ - @Override - public Integer getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - return "null".equalsIgnoreCase(value) ? null : new Integer(getValue(value)); - } - - /** - * This is a primitive type, so we set it specially. - * - * @see ecologylab.serialization.types.ScalarType#setField(Object, Field, String) - */ - @Override - public boolean setField(Object object, Field field, String value) - { - boolean result = false; - int converted = Integer.MIN_VALUE; - try - { - converted = getValue(value); - field.setInt(object, converted); - result = true; - } - catch (Exception e) - { - error("Got " + e + " while setting field " + field + " to " + value + "->" + converted - + " in " + object); - } - return result; - } - - /** - * The string representation for a Field of this type - */ - @Override - public String toString(Field field, Object context) - { - String result = "COULDN'T CONVERT!"; - try - { - result = Integer.toString(field.getInt(context)); - } - catch (Exception e) - { - e.printStackTrace(); - } - return result; - } - - /** - * The default value for this type, as a String. This value is the one that translateToXML(...) - * wont bother emitting. - * - * In this case, "0". - */ - @Override - public String defaultValueString() - { - return DEFAULT_VALUE_STRING; - } - - @Override - public Integer defaultValue() - { - return DEFAULT_VALUE; - } - /** - * True if the value in the Field object matches the default value for this type. - * - * @param field - * @return - */ - @Override - public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, - IllegalAccessException - { - return (context == null) || ((Integer) field.get(context) == null || (Integer) field.get(context) == DEFAULT_VALUE); - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - * - * @param buffy - * @param field - * @param context - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) - throws IllegalArgumentException, IllegalAccessException - { - buffy.append(getValueToAppend(f2xo, context)); - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - * - * @param buffy - * @param context - * @param field - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, - TranslationContext serializationContext, Format format) throws IllegalArgumentException, - IllegalAccessException, IOException - { - buffy.append(getValueToAppend(fieldDescriptor, context)); - } - - public static String getValueToAppend(FieldDescriptor fieldDescriptor, Object context) - throws IllegalArgumentException, IllegalAccessException - { - String result = getNullStringIfNull(fieldDescriptor, context); - if (result == null) - { - result = fieldDescriptor.getField().get(context).toString(); - } - return result; - } - -} +/* + * Created on Dec 31, 2004 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; +import java.lang.reflect.Field; + +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.CrossLanguageTypeConstants; +import ecologylab.serialization.types.ScalarType; + +/** + * Type system entry for int, a built-in primitive. + * + * @author andruid + */ +@simpl_inherit +public class IntType extends ScalarType implements CrossLanguageTypeConstants +{ + public static final int DEFAULT_VALUE = new Integer(0); + + public static final String DEFAULT_VALUE_STRING = "0"; + + /** + * This constructor should only be called once per session, through a static initializer, + * typically in TypeRegistry. + *

+ * To get the instance of this type object for use in translations, call + * TypeRegistry.get("int"). + * + */ + public IntType() + { + this(int.class); + } + + public IntType(Class thatClass) + { + super(thatClass, DOTNET_INTEGER, OBJC_INTEGER, null); + needJsonSerializationQuotation = false; + } + + /** + * Convert the parameter to int. + */ + public int getValue(String valueString) + { + return Integer.parseInt(valueString); + } + + /** + * If this is a reference type, build an appropriate Object, given a String + * representation. If it is a primitive type, return a boxed value. + * + * @param value + * String representation of the instance. + */ + @Override + public Integer getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + return "null".equalsIgnoreCase(value) ? null : new Integer(getValue(value)); + } + + /** + * This is a primitive type, so we set it specially. + * + * @see ecologylab.serialization.types.ScalarType#setField(Object, Field, String) + */ + @Override + public boolean setField(Object object, Field field, String value) + { + boolean result = false; + int converted = Integer.MIN_VALUE; + try + { + converted = getValue(value); + field.setInt(object, converted); + result = true; + } + catch (Exception e) + { + error("Got " + e + " while setting field " + field + " to " + value + "->" + converted + + " in " + object); + } + return result; + } + + /** + * The string representation for a Field of this type + */ + @Override + public String toString(Field field, Object context) + { + String result = "COULDN'T CONVERT!"; + try + { + result = Integer.toString(field.getInt(context)); + } + catch (Exception e) + { + e.printStackTrace(); + } + return result; + } + + /** + * The default value for this type, as a String. This value is the one that translateToXML(...) + * wont bother emitting. + * + * In this case, "0". + */ + @Override + public String defaultValueString() + { + return DEFAULT_VALUE_STRING; + } + + @Override + public Integer defaultValue() + { + return DEFAULT_VALUE; + } + /** + * True if the value in the Field object matches the default value for this type. + * + * @param field + * @return + */ + @Override + public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, + IllegalAccessException + { + return (context == null) || ((Integer) field.get(context) == null || (Integer) field.get(context) == DEFAULT_VALUE); + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * + * @param buffy + * @param field + * @param context + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) + throws IllegalArgumentException, IllegalAccessException + { + buffy.append(getValueToAppend(f2xo, context)); + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * + * @param buffy + * @param context + * @param field + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, + TranslationContext serializationContext, Format format) throws IllegalArgumentException, + IllegalAccessException, IOException + { + buffy.append(getValueToAppend(fieldDescriptor, context)); + } + + public static String getValueToAppend(FieldDescriptor fieldDescriptor, Object context) + throws IllegalArgumentException, IllegalAccessException + { + String result = getNullStringIfNull(fieldDescriptor, context); + if (result == null) + { + result = fieldDescriptor.getField().get(context).toString(); + } + return result; + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/LongType.java b/simplCore/src/ecologylab/serialization/types/scalar/LongType.java index 1fee615f..58e12626 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/LongType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/LongType.java @@ -1,174 +1,175 @@ -/* - * Created on Dec 31, 2004 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.io.IOException; -import java.lang.reflect.Field; - -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.CrossLanguageTypeConstants; -import ecologylab.serialization.types.ScalarType; - -/** - * Type system entry for long, a built-in primitive. - * - * @author andruid - */ -@simpl_inherit -public class LongType extends ScalarType implements CrossLanguageTypeConstants -{ - public static final long DEFAULT_VALUE = 0; - - public static final String DEFAULT_VALUE_STRING = "0"; - - public LongType() - { - this(long.class); - } - - public LongType(Class thatClass) - { - super(thatClass, DOTNET_LONG, OBJC_LONG, null); - } - - /** - * Convert the parameter to long. - */ - public long getValue(String valueString) - { - return Long.parseLong(valueString); - } - - /** - * Parse the String into the (primitive) type, and return a boxed instance. - * - * @param value - * String representation of the instance. - */ - @Override - public Long getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - return "null".equalsIgnoreCase(value) ? null : new Long(value); - } - - /** - * This is a primitive type, so we set it specially. - * - * @see ecologylab.serialization.types.ScalarType#setField(Object, Field, String) - */ - @Override - public boolean setField(Object object, Field field, String value) - { - boolean result = false; - try - { - field.setLong(object, getValue(value)); - result = true; - } - catch (Exception e) - { - setFieldError(field, value, e); - } - return result; - } - - /** - * The string representation for a Field of this type - */ - @Override - public String toString(Field field, Object context) - { - String result = "COULDN'T CONVERT!"; - try - { - result = Long.toString(field.getLong(context)); - } - catch (Exception e) - { - e.printStackTrace(); - } - return result; - } - - /** - * The default value for this type, as a String. This value is the one that translateToXML(...) - * wont bother emitting. - * - * In this case, "0". - */ - @Override - public String defaultValueString() - { - return DEFAULT_VALUE_STRING; - } - - @Override - public Long defaultValue() - { - return DEFAULT_VALUE; - } - - /** - * True if the value in the Field object matches the default value for this type. - * - * @param field - * @return - */ - @Override - public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, - IllegalAccessException - { - return (Long) field.get(context) == DEFAULT_VALUE; - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - * - * @param buffy - * @param field - * @param context - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) - throws IllegalArgumentException, IllegalAccessException - { - buffy.append(getValueToAppend(f2xo, context)); - } - - /** - * Get the value from the Field, in the context. Append its value to the buffy. - * - * @param buffy - * @param context - * @param field - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, - TranslationContext serializationContext, Format format) throws IllegalArgumentException, - IllegalAccessException, IOException - { - buffy.append(getValueToAppend(fieldDescriptor, context)); - } - - public static String getValueToAppend(FieldDescriptor fieldDescriptor, Object context) - throws IllegalArgumentException, IllegalAccessException - { - String result = getNullStringIfNull(fieldDescriptor, context); - if (result == null) - { - result = fieldDescriptor.getField().get(context).toString(); - } - return result; - } - -} +/* + * Created on Dec 31, 2004 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; +import java.lang.reflect.Field; + +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.CrossLanguageTypeConstants; +import ecologylab.serialization.types.ScalarType; + +/** + * Type system entry for long, a built-in primitive. + * + * @author andruid + */ +@simpl_inherit +public class LongType extends ScalarType implements CrossLanguageTypeConstants +{ + public static final long DEFAULT_VALUE = 0; + + public static final String DEFAULT_VALUE_STRING = "0"; + + public LongType() + { + this(long.class); + } + + public LongType(Class thatClass) + { + super(thatClass, DOTNET_LONG, OBJC_LONG, null); + needJsonSerializationQuotation = false; + } + + /** + * Convert the parameter to long. + */ + public long getValue(String valueString) + { + return Long.parseLong(valueString); + } + + /** + * Parse the String into the (primitive) type, and return a boxed instance. + * + * @param value + * String representation of the instance. + */ + @Override + public Long getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + return "null".equalsIgnoreCase(value) ? null : new Long(value); + } + + /** + * This is a primitive type, so we set it specially. + * + * @see ecologylab.serialization.types.ScalarType#setField(Object, Field, String) + */ + @Override + public boolean setField(Object object, Field field, String value) + { + boolean result = false; + try + { + field.setLong(object, getValue(value)); + result = true; + } + catch (Exception e) + { + setFieldError(field, value, e); + } + return result; + } + + /** + * The string representation for a Field of this type + */ + @Override + public String toString(Field field, Object context) + { + String result = "COULDN'T CONVERT!"; + try + { + result = Long.toString(field.getLong(context)); + } + catch (Exception e) + { + e.printStackTrace(); + } + return result; + } + + /** + * The default value for this type, as a String. This value is the one that translateToXML(...) + * wont bother emitting. + * + * In this case, "0". + */ + @Override + public String defaultValueString() + { + return DEFAULT_VALUE_STRING; + } + + @Override + public Long defaultValue() + { + return DEFAULT_VALUE; + } + + /** + * True if the value in the Field object matches the default value for this type. + * + * @param field + * @return + */ + @Override + public boolean isDefaultValue(Field field, Object context) throws IllegalArgumentException, + IllegalAccessException + { + return (Long) field.get(context) == DEFAULT_VALUE; + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * + * @param buffy + * @param field + * @param context + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) + throws IllegalArgumentException, IllegalAccessException + { + buffy.append(getValueToAppend(f2xo, context)); + } + + /** + * Get the value from the Field, in the context. Append its value to the buffy. + * + * @param buffy + * @param context + * @param field + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, + TranslationContext serializationContext, Format format) throws IllegalArgumentException, + IllegalAccessException, IOException + { + buffy.append(getValueToAppend(fieldDescriptor, context)); + } + + public static String getValueToAppend(FieldDescriptor fieldDescriptor, Object context) + throws IllegalArgumentException, IllegalAccessException + { + String result = getNullStringIfNull(fieldDescriptor, context); + if (result == null) + { + result = fieldDescriptor.getField().get(context).toString(); + } + return result; + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/Makefile b/simplCore/src/ecologylab/serialization/types/scalar/Makefile index 753d5f49..d64ce2be 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/Makefile +++ b/simplCore/src/ecologylab/serialization/types/scalar/Makefile @@ -1,16 +1,16 @@ -# current working directory -DIR = ecologylab/types - -JAVA_SRC = Type.java TypeRegistry.java BooleanType.java ByteType.java CharType.java ColorType.java DoubleType.java FloatType.java IntType.java LongType.java ShortType.java StringType.java URLType.java - -JAVA_ROOT= ../../ - -MAKE_DIR = ../../../../makefiles -include $(MAKE_DIR)/applets.make - -cabsign: all - -nsjar: all - -sunjar: all - +# current working directory +DIR = ecologylab/types + +JAVA_SRC = Type.java TypeRegistry.java BooleanType.java ByteType.java CharType.java ColorType.java DoubleType.java FloatType.java IntType.java LongType.java ShortType.java StringType.java URLType.java + +JAVA_ROOT= ../../ + +MAKE_DIR = ../../../../makefiles +include $(MAKE_DIR)/applets.make + +cabsign: all + +nsjar: all + +sunjar: all + diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ParsedURLType.java b/simplCore/src/ecologylab/serialization/types/scalar/ParsedURLType.java index fd6e27f1..40c429d1 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ParsedURLType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ParsedURLType.java @@ -1,205 +1,205 @@ -/* - * Created on Dec 31, 2004 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.io.File; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.regex.Pattern; - -import ecologylab.appframework.PropertiesAndDirectories; -import ecologylab.generic.StringTools; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; - -/** - * Type system entry for java.awt.Color. Uses a hex string as initialization. - * - * @author andruid - */ -@simpl_inherit -public class ParsedURLType extends ReferenceType -implements CrossLanguageTypeConstants -{ -/** - * This constructor should only be called once per session, through - * a static initializer, typically in TypeRegistry. - *

- * To get the instance of this type object for use in translations, call - * TypeRegistry.get("cm.generic.ParsedURL"). - * - */ - public ParsedURLType() - { - super(ParsedURL.class, JAVA_PARSED_URL, DOTNET_PARSED_URL, OBJC_PARSED_URL, null); - } - - private static Pattern spaceRegex = Pattern.compile("\\s"); - - /** - * Looks for file in value, and creates a ParsedURL with file set if appropriate. - * Otherwise, calls ParsedURL.getAbsolute(). - * - * @param value String to marshall into a typed instance. - * - * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], ScalarUnmarshallingContext) - */ - @Override - public ParsedURL getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) - { - File file = null; - if (value.startsWith("file://")) - { - int startIndex = 7; - value = value.substring(startIndex); - try - { - value = URLDecoder.decode(value, "UTF-8"); - } catch (UnsupportedEncodingException e) - { - e.printStackTrace(); - } - file = new File(value); - } - else if (PropertiesAndDirectories.isWindows()) - { - if (value.length() > 1 && value.charAt(1) == ':') - file = ecologylab.io.Files.newFile(value); - else if (value.startsWith("\\\\")) - file = new File(value); - } - if (file != null) - { - return new ParsedURL(file); - } - else - { - - boolean hasUnmarshallingContext = scalarUnmarshallingContext != null; - - if((hasUnmarshallingContext && scalarUnmarshallingContext.fileContext() == null) && spaceRegex.matcher(value).find()) - { - value = value.replaceAll("\\s","%20"); - } - - //TODO -- do we need to check manually here to see if scalarUnmarshallingContext.fileContext() != null? - // or will this resolve a relative file path properly, anyway. -// File fileContext = (scalarUnmarshallingContext == null) ? null : scalarUnmarshallingContext.fileContext(); -// file = (fileContext == null) ? new File(value) : new File(fileContext, value); - - // if no colon in first seven characters, must be relative path - - if (value.lastIndexOf(':', 7) == -1 && hasUnmarshallingContext) - { - // TODO Auto-generated catch block - ParsedURL purlContext = scalarUnmarshallingContext.purlContext(); - if (purlContext != null) - return purlContext.getRelative(value); - } - return ParsedURL.getAbsolute(value, "ParsedURLType.getInstance()"); - } - } - - public static final String URL_DELIMS = "/&?"; - public static final String PRIMARY_URL_DELIM = "/"; - - public static final Pattern URL_DELIMS_TOKENIZER = Pattern.compile("([" + URL_DELIMS + "]*)([^" + URL_DELIMS + "]+)"); - /** - * For editing: these are the valid delimiters for separating tokens that make up a field - * of this type. - * - * @return - */ - @Override - public Pattern delimitersTokenizer() - { - return URL_DELIMS_TOKENIZER; - } - @Override - public String delimeters() - { - return URL_DELIMS; - } - - @Override - public boolean allowNewLines() - { - return false; - } - - /** - * When editing, determines whether delimiters can be included in token strings. - * - * @return true for URLs - */ - //FIXME -- Add String delimitersAfter to TextChunk -- interleaved with TextTokens, and - //get rid of this!!! - @Override - public boolean allowDelimitersInTokens() - { - return true; - } - /** - * When editing, do not allow the user to include these characters in the resulting value String. - * @return - */ - @Override - public String illegalChars() - { - return " !{}\t\n\r"; - } - /** - * When editing, is the field one that should be part of the Term model? - * - * @return false for URLs - */ - @Override - public boolean composedOfTerms() - { - return false; - } - - /** - * The most basic and fundamental delimiter to use between characters. - * - * @return The URL implementation, here, returns a slash. - */ - @Override - public String primaryDelimiter() - { - return PRIMARY_URL_DELIM; - } - - @Override - public String marshall(ParsedURL instance, TranslationContext serializationContext) - { - ParsedURL contextualizedInstance = instance; - if (serializationContext != null) - { - ParsedURL purlContext = serializationContext.purlContext(); - - if (purlContext != null) - { - String instanceProtocol = instance.url().getProtocol(); - String contextProtocol = purlContext.url().getProtocol(); - - if (instanceProtocol.equals(contextProtocol)) - { - int afterProtocolIndex = instanceProtocol.length()+3; - String instanceString = instance.toString().substring(afterProtocolIndex); - String purlContextString = purlContext.toString().substring(afterProtocolIndex); - - String pathRelativeTo = StringTools.getPathRelativeTo(instanceString, purlContextString, '/'); - if (pathRelativeTo != null) - return pathRelativeTo; - } - } - } - - return super.marshall(contextualizedInstance, serializationContext); - } -} +/* + * Created on Dec 31, 2004 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.regex.Pattern; + +import ecologylab.appframework.PropertiesAndDirectories; +import ecologylab.generic.StringTools; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +/** + * Type system entry for java.awt.Color. Uses a hex string as initialization. + * + * @author andruid + */ +@simpl_inherit +public class ParsedURLType extends ReferenceType +implements CrossLanguageTypeConstants +{ +/** + * This constructor should only be called once per session, through + * a static initializer, typically in TypeRegistry. + *

+ * To get the instance of this type object for use in translations, call + * TypeRegistry.get("cm.generic.ParsedURL"). + * + */ + public ParsedURLType() + { + super(ParsedURL.class, JAVA_PARSED_URL, DOTNET_PARSED_URL, OBJC_PARSED_URL, null); + } + + private static Pattern spaceRegex = Pattern.compile("\\s"); + + /** + * Looks for file in value, and creates a ParsedURL with file set if appropriate. + * Otherwise, calls ParsedURL.getAbsolute(). + * + * @param value String to marshall into a typed instance. + * + * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], ScalarUnmarshallingContext) + */ + @Override + public ParsedURL getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) + { + File file = null; + if (value.startsWith("file://")) + { + int startIndex = 7; + value = value.substring(startIndex); + try + { + value = URLDecoder.decode(value, "UTF-8"); + } catch (UnsupportedEncodingException e) + { + e.printStackTrace(); + } + file = new File(value); + } + else if (PropertiesAndDirectories.isWindows()) + { + if (value.length() > 1 && value.charAt(1) == ':') + file = ecologylab.io.Files.newFile(value); + else if (value.startsWith("\\\\")) + file = new File(value); + } + if (file != null) + { + return new ParsedURL(file); + } + else + { + + boolean hasUnmarshallingContext = scalarUnmarshallingContext != null; + + if((hasUnmarshallingContext && scalarUnmarshallingContext.fileContext() == null) && spaceRegex.matcher(value).find()) + { + value = value.replaceAll("\\s","%20"); + } + + //TODO -- do we need to check manually here to see if scalarUnmarshallingContext.fileContext() != null? + // or will this resolve a relative file path properly, anyway. +// File fileContext = (scalarUnmarshallingContext == null) ? null : scalarUnmarshallingContext.fileContext(); +// file = (fileContext == null) ? new File(value) : new File(fileContext, value); + + // if no colon in first seven characters, must be relative path + + if (value.lastIndexOf(':', 7) == -1 && hasUnmarshallingContext) + { + // TODO Auto-generated catch block + ParsedURL purlContext = scalarUnmarshallingContext.purlContext(); + if (purlContext != null) + return purlContext.getRelative(value); + } + return ParsedURL.getAbsolute(value, "ParsedURLType.getInstance()"); + } + } + + public static final String URL_DELIMS = "/&?"; + public static final String PRIMARY_URL_DELIM = "/"; + + public static final Pattern URL_DELIMS_TOKENIZER = Pattern.compile("([" + URL_DELIMS + "]*)([^" + URL_DELIMS + "]+)"); + /** + * For editing: these are the valid delimiters for separating tokens that make up a field + * of this type. + * + * @return + */ + @Override + public Pattern delimitersTokenizer() + { + return URL_DELIMS_TOKENIZER; + } + @Override + public String delimeters() + { + return URL_DELIMS; + } + + @Override + public boolean allowNewLines() + { + return false; + } + + /** + * When editing, determines whether delimiters can be included in token strings. + * + * @return true for URLs + */ + //FIXME -- Add String delimitersAfter to TextChunk -- interleaved with TextTokens, and + //get rid of this!!! + @Override + public boolean allowDelimitersInTokens() + { + return true; + } + /** + * When editing, do not allow the user to include these characters in the resulting value String. + * @return + */ + @Override + public String illegalChars() + { + return " !{}\t\n\r"; + } + /** + * When editing, is the field one that should be part of the Term model? + * + * @return false for URLs + */ + @Override + public boolean composedOfTerms() + { + return false; + } + + /** + * The most basic and fundamental delimiter to use between characters. + * + * @return The URL implementation, here, returns a slash. + */ + @Override + public String primaryDelimiter() + { + return PRIMARY_URL_DELIM; + } + + @Override + public String marshall(ParsedURL instance, TranslationContext serializationContext) + { + ParsedURL contextualizedInstance = instance; + if (serializationContext != null) + { + ParsedURL purlContext = serializationContext.purlContext(); + + if (purlContext != null) + { + String instanceProtocol = instance.url().getProtocol(); + String contextProtocol = purlContext.url().getProtocol(); + + if (instanceProtocol.equals(contextProtocol)) + { + int afterProtocolIndex = instanceProtocol.length()+3; + String instanceString = instance.toString().substring(afterProtocolIndex); + String purlContextString = purlContext.toString().substring(afterProtocolIndex); + + String pathRelativeTo = StringTools.getPathRelativeTo(instanceString, purlContextString, '/'); + if (pathRelativeTo != null) + return pathRelativeTo; + } + } + } + + return super.marshall(contextualizedInstance, serializationContext); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceBooleanType.java b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceBooleanType.java index 8cf2543e..c1f0ddd8 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceBooleanType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceBooleanType.java @@ -1,14 +1,14 @@ -package ecologylab.serialization.types.scalar; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; - -@simpl_inherit -public class ReferenceBooleanType extends BooleanType -implements CrossLanguageTypeConstants -{ - public ReferenceBooleanType() - { - super(Boolean.class); - } -} +package ecologylab.serialization.types.scalar; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +@simpl_inherit +public class ReferenceBooleanType extends BooleanType +implements CrossLanguageTypeConstants +{ + public ReferenceBooleanType() + { + super(Boolean.class); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceByteType.java b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceByteType.java index 093f5f95..2859d05c 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceByteType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceByteType.java @@ -1,8 +1,8 @@ -package ecologylab.serialization.types.scalar; - -public class ReferenceByteType extends ByteType{ - public ReferenceByteType() - { - super(Byte.class); - } -} +package ecologylab.serialization.types.scalar; + +public class ReferenceByteType extends ByteType{ + public ReferenceByteType() + { + super(Byte.class); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceCharType.java b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceCharType.java index 943e192c..24172a0d 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceCharType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceCharType.java @@ -1,8 +1,8 @@ -package ecologylab.serialization.types.scalar; - -public class ReferenceCharType extends CharType { - public ReferenceCharType() - { - super(Character.class); - } -} +package ecologylab.serialization.types.scalar; + +public class ReferenceCharType extends CharType { + public ReferenceCharType() + { + super(Character.class); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceDoubleType.java b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceDoubleType.java index c9d25fe5..942e3134 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceDoubleType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceDoubleType.java @@ -1,18 +1,18 @@ -package ecologylab.serialization.types.scalar; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; - -/** - * Entry for boxed Double. - * - * @author andruid - */ -@simpl_inherit -public class ReferenceDoubleType extends DoubleType implements CrossLanguageTypeConstants -{ - public ReferenceDoubleType() - { - super(Double.class); - } -} +package ecologylab.serialization.types.scalar; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +/** + * Entry for boxed Double. + * + * @author andruid + */ +@simpl_inherit +public class ReferenceDoubleType extends DoubleType implements CrossLanguageTypeConstants +{ + public ReferenceDoubleType() + { + super(Double.class); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceFloatType.java b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceFloatType.java index f67caacd..62f0a867 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceFloatType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceFloatType.java @@ -1,19 +1,19 @@ -package ecologylab.serialization.types.scalar; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; - -/** - * Entry for boxed Float. - * - * @author andruid - */ -@simpl_inherit -public class ReferenceFloatType extends FloatType -implements CrossLanguageTypeConstants -{ - public ReferenceFloatType() - { - super(Float.class); - } -} +package ecologylab.serialization.types.scalar; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +/** + * Entry for boxed Float. + * + * @author andruid + */ +@simpl_inherit +public class ReferenceFloatType extends FloatType +implements CrossLanguageTypeConstants +{ + public ReferenceFloatType() + { + super(Float.class); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceIntegerType.java b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceIntegerType.java index 69c042e8..53cd4433 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceIntegerType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceIntegerType.java @@ -1,15 +1,15 @@ -package ecologylab.serialization.types.scalar; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; - -@simpl_inherit -public class ReferenceIntegerType extends IntType -implements CrossLanguageTypeConstants -{ - public ReferenceIntegerType() - { - super(Integer.class); - } - -} +package ecologylab.serialization.types.scalar; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +@simpl_inherit +public class ReferenceIntegerType extends IntType +implements CrossLanguageTypeConstants +{ + public ReferenceIntegerType() + { + super(Integer.class); + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceLongType.java b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceLongType.java index f3f360d3..67a82032 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceLongType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceLongType.java @@ -1,15 +1,15 @@ -package ecologylab.serialization.types.scalar; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; - -@simpl_inherit -public class ReferenceLongType extends LongType -implements CrossLanguageTypeConstants -{ - public ReferenceLongType() - { - super(Long.class); - } - -} +package ecologylab.serialization.types.scalar; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +@simpl_inherit +public class ReferenceLongType extends LongType +implements CrossLanguageTypeConstants +{ + public ReferenceLongType() + { + super(Long.class); + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceShortType.java b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceShortType.java index 6672e5ee..42178a1f 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceShortType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceShortType.java @@ -1,8 +1,8 @@ -package ecologylab.serialization.types.scalar; - -public class ReferenceShortType extends ShortType { - public ReferenceShortType() - { - super(Short.class); - } -} +package ecologylab.serialization.types.scalar; + +public class ReferenceShortType extends ShortType { + public ReferenceShortType() + { + super(Short.class); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceType.java b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceType.java index c39bfb13..b0249255 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ReferenceType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ReferenceType.java @@ -1,95 +1,95 @@ -/** - * - */ -package ecologylab.serialization.types.scalar; - -import java.io.IOException; - -import org.json.simple.JSONObject; - -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.ScalarType; - -/** - * All non-primitive ScalarType subclasses should extend this class. - * - * @author andruid - */ -@simpl_inherit -abstract public class ReferenceType extends ScalarType -{ - - public ReferenceType() - { - - } - - /** - * @param thatClass - * @param javaTypeName - * TODO - * @param cSharpTypeName - * TODO - * @param objectiveCTypeName - * TODO - * @param dbTypeName - * TODO - */ - public ReferenceType(Class thatClass, String javaTypeName, String cSharpTypeName, - String objectiveCTypeName, String dbTypeName) - { - super(thatClass, cSharpTypeName, objectiveCTypeName, dbTypeName); - } - - /** - * Append the String directly, unless it needs escaping, in which case, call escapeXML. - * - * @param instance - * @param buffy - * @param needsEscaping - */ - @Override - public void appendValue(T instance, StringBuilder buffy, boolean needsEscaping, - TranslationContext serializationContext) - { - - String instanceString = marshall(instance, serializationContext);// instance.toString(); - if (needsEscaping) - XMLTools.escapeXML(buffy, instanceString); - else - buffy.append(instanceString); - } - - @Override - public void appendValue(T instance, Appendable buffy, boolean needsEscaping, - TranslationContext serializationContext, Format format) throws IOException - { - String instanceString = ""; - if (instance != null && serializationContext != null) - instanceString = marshall(instance, serializationContext); // andruid 1/4/10 - // instance.toString(); - if (needsEscaping) - { - switch (format) - { - case JSON: - buffy.append(JSONObject.escape(instanceString)); - ; - break; - case XML: - XMLTools.escapeXML(buffy, instanceString); - break; - default: - XMLTools.escapeXML(buffy, instanceString); - break; - } - - } - else - buffy.append(instanceString); - } - -} +/** + * + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; + +import org.json.simple.JSONObject; + +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.ScalarType; + +/** + * All non-primitive ScalarType subclasses should extend this class. + * + * @author andruid + */ +@simpl_inherit +abstract public class ReferenceType extends ScalarType +{ + + public ReferenceType() + { + + } + + /** + * @param thatClass + * @param javaTypeName + * TODO + * @param cSharpTypeName + * TODO + * @param objectiveCTypeName + * TODO + * @param dbTypeName + * TODO + */ + public ReferenceType(Class thatClass, String javaTypeName, String cSharpTypeName, + String objectiveCTypeName, String dbTypeName) + { + super(thatClass, cSharpTypeName, objectiveCTypeName, dbTypeName); + } + + /** + * Append the String directly, unless it needs escaping, in which case, call escapeXML. + * + * @param instance + * @param buffy + * @param needsEscaping + */ + @Override + public void appendValue(T instance, StringBuilder buffy, boolean needsEscaping, + TranslationContext serializationContext) + { + + String instanceString = marshall(instance, serializationContext);// instance.toString(); + if (needsEscaping) + XMLTools.escapeXML(buffy, instanceString); + else + buffy.append(instanceString); + } + + @Override + public void appendValue(T instance, Appendable buffy, boolean needsEscaping, + TranslationContext serializationContext, Format format) throws IOException + { + String instanceString = ""; + if (instance != null && serializationContext != null) + instanceString = marshall(instance, serializationContext); // andruid 1/4/10 + // instance.toString(); + if (needsEscaping) + { + switch (format) + { + case JSON: + buffy.append(JSONObject.escape(instanceString)); + ; + break; + case XML: + XMLTools.escapeXML(buffy, instanceString); + break; + default: + XMLTools.escapeXML(buffy, instanceString); + break; + } + + } + else + buffy.append(instanceString); + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ScalarTypeType.java b/simplCore/src/ecologylab/serialization/types/scalar/ScalarTypeType.java index 1fba35d2..3a271a0c 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ScalarTypeType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ScalarTypeType.java @@ -1,65 +1,65 @@ -/** - * - */ -package ecologylab.serialization.types.scalar; - -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.TypeRegistry; - -/** - * For storing actual ScalarType values as meta-metadata. - * - * @author andruid - * - */ -@simpl_inherit -public class ScalarTypeType extends ReferenceType -implements CrossLanguageTypeConstants -{ - /** - * @param javaClass - */ - public ScalarTypeType() - { - super(ScalarType.class, JAVA_SCALAR_TYPE, DOTNET_SCALAR_TYPE, OBJC_SCALAR_TYPE, null); - } - - /** - * Capitalize the value if it wasn't. - * Append "Type". - * Use this to call TypeRegistry.getType(). - */ - @Override - public ScalarType getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) - { - ScalarType result = null; - int length = value.length(); - if ((value != null) && (length > 0)) - { - char firstChar = value.charAt(0); - StringBuilder buffy = new StringBuilder(length + 4); // includes room for "Type" - if (Character.isLowerCase(firstChar)) - { - buffy.append(Character.toUpperCase(firstChar)); - if (length > 1) - buffy.append(value, 1, length - 1); - } - else - buffy.append(value); -// buffy.append("Type"); //TODO -- verify that this change is correct -- andruid & yin 7/21/2011 - - result = TypeRegistry.getScalarTypeBySimpleName(buffy.toString()); - } - return result; - } - - @Override - public String marshall(ScalarType instance, TranslationContext serializationContext) - { - return instance.getJavaClass().getSimpleName(); - } -} +/** + * + */ +package ecologylab.serialization.types.scalar; + +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.TypeRegistry; + +/** + * For storing actual ScalarType values as meta-metadata. + * + * @author andruid + * + */ +@simpl_inherit +public class ScalarTypeType extends ReferenceType +implements CrossLanguageTypeConstants +{ + /** + * @param javaClass + */ + public ScalarTypeType() + { + super(ScalarType.class, JAVA_SCALAR_TYPE, DOTNET_SCALAR_TYPE, OBJC_SCALAR_TYPE, null); + } + + /** + * Capitalize the value if it wasn't. + * Append "Type". + * Use this to call TypeRegistry.getType(). + */ + @Override + public ScalarType getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) + { + ScalarType result = null; + int length = value.length(); + if ((value != null) && (length > 0)) + { + char firstChar = value.charAt(0); + StringBuilder buffy = new StringBuilder(length + 4); // includes room for "Type" + if (Character.isLowerCase(firstChar)) + { + buffy.append(Character.toUpperCase(firstChar)); + if (length > 1) + buffy.append(value, 1, length - 1); + } + else + buffy.append(value); +// buffy.append("Type"); //TODO -- verify that this change is correct -- andruid & yin 7/21/2011 + + result = TypeRegistry.getScalarTypeBySimpleName(buffy.toString()); + } + return result; + } + + @Override + public String marshall(ScalarType instance, TranslationContext serializationContext) + { + return instance.getJavaClass().getSimpleName(); + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/ShortType.java b/simplCore/src/ecologylab/serialization/types/scalar/ShortType.java index c233899d..ee589b01 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/ShortType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/ShortType.java @@ -1,162 +1,164 @@ -/* - * Created on Dec 31, 2004 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.io.IOException; -import java.lang.reflect.Field; - -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.CrossLanguageTypeConstants; -import ecologylab.serialization.types.ScalarType; - -/** - * Type system entry for short, a built-in primitive. - * - * @author andruid - */ -@simpl_inherit -public class ShortType extends ScalarType -{ - public static final short DEFAULT_VALUE = 0; - public static final String DEFAULT_VALUE_STRING = "0"; - -/** - * This constructor should only be called once per session, through - * a static initializer, typically in TypeRegistry. - *

- * To get the instance of this type object for use in translations, call - * TypeRegistry.get("short"). - * - */ - public ShortType() - { - super(short.class, CrossLanguageTypeConstants.DOTNET_SHORT, CrossLanguageTypeConstants.OBJC_SHORT, null); - } - - public ShortType(Class class1) - { - super(class1, CrossLanguageTypeConstants.DOTNET_SHORT, CrossLanguageTypeConstants.OBJC_SHORT, null); - } - - /** - * Convert the parameter to short. - */ - public short getValue(String valueString) - { - return Short.parseShort(valueString); - } - - /** - * Parse the String into the (primitive) type, and return a boxed instance. - * - * @param value - * String representation of the instance. - */ - @Override - public Short getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) - { - return new Short(value); - } - - /** - * This is a primitive type, so we set it specially. - * - * @see ecologylab.serialization.types.ScalarType#setField(Object, Field, String) - */ - public boolean setField(Field field, String value) - { - boolean result = false; - try - { - field.setShort(this, getValue(value)); - result = true; - } catch (Exception e) - { - setFieldError(field, value, e); - } - return result; - } -/** - * The string representation for a Field of this type - */ - @Override - public String toString(Field field, Object context) - { - String result = "COULDN'T CONVERT!"; - try - { - result = Short.toString(field.getShort(context)); - } catch (Exception e) - { - e.printStackTrace(); - } - return result; - } - - /** - * The default value for this type, as a String. - * This value is the one that translateToXML(...) wont bother emitting. - * - * In this case, "0". - */ - @Override - public String defaultValueString() - { - return DEFAULT_VALUE_STRING; - } - - /** - * True if the value in the Field object matches the default value for this type. - * - * @param field - * @return - */ - @Override public boolean isDefaultValue(Field field, Object context) - throws IllegalArgumentException, IllegalAccessException - { - return field.getShort(context) == DEFAULT_VALUE; - } - - /** - * Get the value from the Field, in the context. - * Append its value to the buffy. - * - * @param buffy - * @param field - * @param context - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) - throws IllegalArgumentException, IllegalAccessException - { - short value = f2xo.getField().getShort(context); - - buffy.append(value); - } - /** - * Get the value from the Field, in the context. - * Append its value to the buffy. - * - * @param buffy - * @param context - * @param field - * @throws IllegalAccessException - * @throws IllegalArgumentException - */ - @Override - public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, TranslationContext serializationContext, Format format) - throws IllegalArgumentException, IllegalAccessException, IOException - { - short value = fieldDescriptor.getField().getShort(context); - - buffy.append(Short.toString(value)); - } - -} +/* + * Created on Dec 31, 2004 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; +import java.lang.reflect.Field; + +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.CrossLanguageTypeConstants; +import ecologylab.serialization.types.ScalarType; + +/** + * Type system entry for short, a built-in primitive. + * + * @author andruid + */ +@simpl_inherit +public class ShortType extends ScalarType +{ + public static final short DEFAULT_VALUE = 0; + public static final String DEFAULT_VALUE_STRING = "0"; + +/** + * This constructor should only be called once per session, through + * a static initializer, typically in TypeRegistry. + *

+ * To get the instance of this type object for use in translations, call + * TypeRegistry.get("short"). + * + */ + public ShortType() + { + super(short.class, CrossLanguageTypeConstants.DOTNET_SHORT, CrossLanguageTypeConstants.OBJC_SHORT, null); + needJsonSerializationQuotation = false; + } + + public ShortType(Class class1) + { + super(class1, CrossLanguageTypeConstants.DOTNET_SHORT, CrossLanguageTypeConstants.OBJC_SHORT, null); + needJsonSerializationQuotation = false; + } + + /** + * Convert the parameter to short. + */ + public short getValue(String valueString) + { + return Short.parseShort(valueString); + } + + /** + * Parse the String into the (primitive) type, and return a boxed instance. + * + * @param value + * String representation of the instance. + */ + @Override + public Short getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) + { + return new Short(value); + } + + /** + * This is a primitive type, so we set it specially. + * + * @see ecologylab.serialization.types.ScalarType#setField(Object, Field, String) + */ + public boolean setField(Field field, String value) + { + boolean result = false; + try + { + field.setShort(this, getValue(value)); + result = true; + } catch (Exception e) + { + setFieldError(field, value, e); + } + return result; + } +/** + * The string representation for a Field of this type + */ + @Override + public String toString(Field field, Object context) + { + String result = "COULDN'T CONVERT!"; + try + { + result = Short.toString(field.getShort(context)); + } catch (Exception e) + { + e.printStackTrace(); + } + return result; + } + + /** + * The default value for this type, as a String. + * This value is the one that translateToXML(...) wont bother emitting. + * + * In this case, "0". + */ + @Override + public String defaultValueString() + { + return DEFAULT_VALUE_STRING; + } + + /** + * True if the value in the Field object matches the default value for this type. + * + * @param field + * @return + */ + @Override public boolean isDefaultValue(Field field, Object context) + throws IllegalArgumentException, IllegalAccessException + { + return field.getShort(context) == DEFAULT_VALUE; + } + + /** + * Get the value from the Field, in the context. + * Append its value to the buffy. + * + * @param buffy + * @param field + * @param context + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(StringBuilder buffy, FieldDescriptor f2xo, Object context) + throws IllegalArgumentException, IllegalAccessException + { + short value = f2xo.getField().getShort(context); + + buffy.append(value); + } + /** + * Get the value from the Field, in the context. + * Append its value to the buffy. + * + * @param buffy + * @param context + * @param field + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + @Override + public void appendValue(Appendable buffy, FieldDescriptor fieldDescriptor, Object context, TranslationContext serializationContext, Format format) + throws IllegalArgumentException, IllegalAccessException, IOException + { + short value = fieldDescriptor.getField().getShort(context); + + buffy.append(Short.toString(value)); + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/StringBuilderType.java b/simplCore/src/ecologylab/serialization/types/scalar/StringBuilderType.java index cae92835..151402ad 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/StringBuilderType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/StringBuilderType.java @@ -1,101 +1,101 @@ -/* - * Created on Dec 31, 2004 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.io.IOException; - -import org.json.simple.JSONObject; - -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.CrossLanguageTypeConstants; - -/** - * Type system entry for {@link java.lang.String String}. A very simple case. - * - * @author andruid - */ -@simpl_inherit -public class StringBuilderType extends ReferenceType implements - CrossLanguageTypeConstants -{ - /** - * This constructor should only be called once per session, through a static initializer, - * typically in TypeRegistry. - *

- * To get the instance of this type object for use in translations, call - * TypeRegistry.get("java.lang.String"). - * - */ - public StringBuilderType() - { - super(StringBuilder.class, JAVA_STRING_BUILDER, DOTNET_STRING_BUILDER, OBJC_STRING_BUILDER, - null); - } - - /** - * Return the value wrapped inside a StringBuilder. A call to avoid! - * - * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], - * ScalarUnmarshallingContext) - */ - @Override - public StringBuilder getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - return new StringBuilder(value); - } - - @Override - public void appendValue(StringBuilder instance, StringBuilder buffy, boolean needsEscaping, - TranslationContext serializationContext) - { - if (needsEscaping) - XMLTools.escapeXML(buffy, instance); - else - buffy.append(instance); - } - - @Override - public void appendValue(StringBuilder instance, Appendable appendable, boolean needsEscaping, - TranslationContext serializationContext, Format format) throws IOException - { - if (needsEscaping) - { - switch (format) - { - case JSON: - appendable.append(JSONObject.escape(instance.toString())); - break; - case XML: - XMLTools.escapeXML(appendable, instance); - break; - default: - XMLTools.escapeXML(appendable, instance); - break; - } - - } - else - appendable.append(instance); - - } - - /** - * When editing, determines whether delimiters can be included in token strings. - * - * @return - */ - // FIXME -- Add String delimitersAfter to TextChunk -- interleaved with TextTokens, and - // get rid of this!!! - @Override - public boolean allowDelimitersInTokens() - { - return true; - } - -} +/* + * Created on Dec 31, 2004 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; + +import org.json.simple.JSONObject; + +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +/** + * Type system entry for {@link java.lang.String String}. A very simple case. + * + * @author andruid + */ +@simpl_inherit +public class StringBuilderType extends ReferenceType implements + CrossLanguageTypeConstants +{ + /** + * This constructor should only be called once per session, through a static initializer, + * typically in TypeRegistry. + *

+ * To get the instance of this type object for use in translations, call + * TypeRegistry.get("java.lang.String"). + * + */ + public StringBuilderType() + { + super(StringBuilder.class, JAVA_STRING_BUILDER, DOTNET_STRING_BUILDER, OBJC_STRING_BUILDER, + null); + } + + /** + * Return the value wrapped inside a StringBuilder. A call to avoid! + * + * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], + * ScalarUnmarshallingContext) + */ + @Override + public StringBuilder getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + return new StringBuilder(value); + } + + @Override + public void appendValue(StringBuilder instance, StringBuilder buffy, boolean needsEscaping, + TranslationContext serializationContext) + { + if (needsEscaping) + XMLTools.escapeXML(buffy, instance); + else + buffy.append(instance); + } + + @Override + public void appendValue(StringBuilder instance, Appendable appendable, boolean needsEscaping, + TranslationContext serializationContext, Format format) throws IOException + { + if (needsEscaping) + { + switch (format) + { + case JSON: + appendable.append(JSONObject.escape(instance.toString())); + break; + case XML: + XMLTools.escapeXML(appendable, instance); + break; + default: + XMLTools.escapeXML(appendable, instance); + break; + } + + } + else + appendable.append(instance); + + } + + /** + * When editing, determines whether delimiters can be included in token strings. + * + * @return + */ + // FIXME -- Add String delimitersAfter to TextChunk -- interleaved with TextTokens, and + // get rid of this!!! + @Override + public boolean allowDelimitersInTokens() + { + return true; + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/StringType.java b/simplCore/src/ecologylab/serialization/types/scalar/StringType.java index 6c9c5b20..e1bc4f09 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/StringType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/StringType.java @@ -1,124 +1,124 @@ -/* - * Created on Dec 31, 2004 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.io.IOException; - -import org.json.simple.JSONObject; - -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.CrossLanguageTypeConstants; - -/** - * Type system entry for {@link java.lang.String String}. A very simple case. - * - * @author andruid - */ -@simpl_inherit -public class StringType extends ReferenceType implements CrossLanguageTypeConstants -{ - /** - * This constructor should only be called once per session, through a static initializer, - * typically in TypeRegistry. - *

- * To get the instance of this type object for use in translations, call - * TypeRegistry.get("java.lang.String"). - * - */ - public StringType() - { - super(String.class, JAVA_STRING, DOTNET_STRING, OBJC_STRING, null); - } - - /** - * Just return the value itself. A transparent pass-through. - * - * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], - * ScalarUnmarshallingContext) - */ - @Override - public String getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - return value; - } - - /** - * Get a String representation of the instance, which is simply this. - * - * @param instance - * @return - */ - @Override - public String marshall(String instance, TranslationContext serializationContext) - { - return instance; - } - - /** - * Append the String directly, unless it needs escaping, in which case, call escapeXML. - * - * @param instance - * @param buffy - * @param needsEscaping - */ - @Override - public void appendValue(String instance, StringBuilder buffy, boolean needsEscaping, - TranslationContext serializationContext) - { - - if (needsEscaping) - XMLTools.escapeXML(buffy, instance); - else - buffy.append(instance); - } - - /** - * Append the String directly, unless it needs escaping, in which case, call escapeXML. - * - * @param instance - * @param appendable - * @param needsEscaping - * @throws IOException - */ - @Override - public void appendValue(String instance, Appendable appendable, boolean needsEscaping, - TranslationContext serializationContext, Format format) throws IOException - { - if (needsEscaping) - { - switch (format) - { - case JSON: - appendable.append(JSONObject.escape(instance)); - break; - case XML: - XMLTools.escapeXML(appendable, instance); - break; - default: - XMLTools.escapeXML(appendable, instance); - break; - } - } - else - appendable.append(instance); - } - - /** - * When editing, determines whether delimiters can be included in token strings. - * - * @return - */ - // FIXME -- Add String delimitersAfter to TextChunk -- interleaved with TextTokens, and - // get rid of this!!! - @Override - public boolean allowDelimitersInTokens() - { - return true; - } -} +/* + * Created on Dec 31, 2004 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.io.IOException; + +import org.json.simple.JSONObject; + +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +/** + * Type system entry for {@link java.lang.String String}. A very simple case. + * + * @author andruid + */ +@simpl_inherit +public class StringType extends ReferenceType implements CrossLanguageTypeConstants +{ + /** + * This constructor should only be called once per session, through a static initializer, + * typically in TypeRegistry. + *

+ * To get the instance of this type object for use in translations, call + * TypeRegistry.get("java.lang.String"). + * + */ + public StringType() + { + super(String.class, JAVA_STRING, DOTNET_STRING, OBJC_STRING, null); + } + + /** + * Just return the value itself. A transparent pass-through. + * + * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], + * ScalarUnmarshallingContext) + */ + @Override + public String getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + return value; + } + + /** + * Get a String representation of the instance, which is simply this. + * + * @param instance + * @return + */ + @Override + public String marshall(String instance, TranslationContext serializationContext) + { + return instance; + } + + /** + * Append the String directly, unless it needs escaping, in which case, call escapeXML. + * + * @param instance + * @param buffy + * @param needsEscaping + */ + @Override + public void appendValue(String instance, StringBuilder buffy, boolean needsEscaping, + TranslationContext serializationContext) + { + + if (needsEscaping) + XMLTools.escapeXML(buffy, instance); + else + buffy.append(instance); + } + + /** + * Append the String directly, unless it needs escaping, in which case, call escapeXML. + * + * @param instance + * @param appendable + * @param needsEscaping + * @throws IOException + */ + @Override + public void appendValue(String instance, Appendable appendable, boolean needsEscaping, + TranslationContext serializationContext, Format format) throws IOException + { + if (needsEscaping) + { + switch (format) + { + case JSON: + appendable.append(JSONObject.escape(instance)); + break; + case XML: + XMLTools.escapeXML(appendable, instance); + break; + default: + XMLTools.escapeXML(appendable, instance); + break; + } + } + else + appendable.append(instance); + } + + /** + * When editing, determines whether delimiters can be included in token strings. + * + * @return + */ + // FIXME -- Add String delimitersAfter to TextChunk -- interleaved with TextTokens, and + // get rid of this!!! + @Override + public boolean allowDelimitersInTokens() + { + return true; + } +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/URLType.java b/simplCore/src/ecologylab/serialization/types/scalar/URLType.java index a1850366..ddc57ac0 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/URLType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/URLType.java @@ -1,77 +1,77 @@ -/* - * Created on Jan 2, 2005 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.regex.Pattern; - -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; - -/** - * Type system entry for {@link java.net.URL URL}. - * This should almost never be used. - * ParsedURLType is preferred! - * - * @author andruid - */ -@simpl_inherit -public class URLType extends ReferenceType -implements CrossLanguageTypeConstants -{ - public URLType() - { - super(URL.class, JAVA_URL, DOTNET_URL, OBJC_URL, null); - } - - /** - * @param value is interpreted as an absolute internet address. - * - * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], ScalarUnmarshallingContext) - */ - @Override - public URL getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) - { - URL result = null; - try - { - result = new URL(value); - } catch (MalformedURLException e) - { - debug("Got " + e + " while setting getting instance of URL from " - + value); - } - return result; - } - /** - * For editing: these are the valid delimiters for separating tokens that make up a field - * of this type. - * - * @return - */ - @Override - public Pattern delimitersTokenizer() - { - return ParsedURLType.URL_DELIMS_TOKENIZER; - } - @Override - public String delimeters() - { - return ParsedURLType.URL_DELIMS; - } - - /** - * The most basic and fundamental delimiter to use between characters. - * - * @return The URL implementation, here, returns a slash. - */ - @Override - public String primaryDelimiter() - { - return ParsedURLType.PRIMARY_URL_DELIM; - } - -} +/* + * Created on Jan 2, 2005 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.regex.Pattern; + +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; + +/** + * Type system entry for {@link java.net.URL URL}. + * This should almost never be used. + * ParsedURLType is preferred! + * + * @author andruid + */ +@simpl_inherit +public class URLType extends ReferenceType +implements CrossLanguageTypeConstants +{ + public URLType() + { + super(URL.class, JAVA_URL, DOTNET_URL, OBJC_URL, null); + } + + /** + * @param value is interpreted as an absolute internet address. + * + * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], ScalarUnmarshallingContext) + */ + @Override + public URL getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) + { + URL result = null; + try + { + result = new URL(value); + } catch (MalformedURLException e) + { + debug("Got " + e + " while setting getting instance of URL from " + + value); + } + return result; + } + /** + * For editing: these are the valid delimiters for separating tokens that make up a field + * of this type. + * + * @return + */ + @Override + public Pattern delimitersTokenizer() + { + return ParsedURLType.URL_DELIMS_TOKENIZER; + } + @Override + public String delimeters() + { + return ParsedURLType.URL_DELIMS; + } + + /** + * The most basic and fundamental delimiter to use between characters. + * + * @return The URL implementation, here, returns a slash. + */ + @Override + public String primaryDelimiter() + { + return ParsedURLType.PRIMARY_URL_DELIM; + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/UUIDType.java b/simplCore/src/ecologylab/serialization/types/scalar/UUIDType.java index 08f7ad93..c8bb2320 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/UUIDType.java +++ b/simplCore/src/ecologylab/serialization/types/scalar/UUIDType.java @@ -1,32 +1,32 @@ -package ecologylab.serialization.types.scalar; - -import java.util.UUID; - -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; -import ecologylab.serialization.types.ScalarType; - -@simpl_inherit -public class UUIDType extends ScalarType -implements CrossLanguageTypeConstants -{ - - public UUIDType() - { - this(UUID.class); - } - - public UUIDType(Class clazz) - { - super(clazz, DOTNET_UUID, null, null); - } - - @Override - public UUID getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - return UUID.fromString(value); - } - -} +package ecologylab.serialization.types.scalar; + +import java.util.UUID; + +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; +import ecologylab.serialization.types.ScalarType; + +@simpl_inherit +public class UUIDType extends ScalarType +implements CrossLanguageTypeConstants +{ + + public UUIDType() + { + this(UUID.class); + } + + public UUIDType(Class clazz) + { + super(clazz, DOTNET_UUID, null, null); + } + + @Override + public UUID getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + return UUID.fromString(value); + } + +} diff --git a/simplCore/src/ecologylab/serialization/types/scalar/package.html b/simplCore/src/ecologylab/serialization/types/scalar/package.html index 6a308a1b..a1477504 100644 --- a/simplCore/src/ecologylab/serialization/types/scalar/package.html +++ b/simplCore/src/ecologylab/serialization/types/scalar/package.html @@ -1,8 +1,8 @@ - -Provides an extensible type system for translating fields to and from String -representations. Comes with support for primitive types and common -reference types, such as String, Color, and URL. Includes -straightforward facilities for extension to support any -type. Specifically, to add support for a new type, extend the -{@link ecologylab.xml.types.scalar.Type Type} class. - + +Provides an extensible type system for translating fields to and from String +representations. Comes with support for primitive types and common +reference types, such as String, Color, and URL. Includes +straightforward facilities for extension to support any +type. Specifically, to add support for a new type, extend the +{@link ecologylab.xml.types.scalar.Type Type} class. + diff --git a/simplCore/src/ecologylab/sql/ConnectionWithAutoClose.java b/simplCore/src/ecologylab/sql/ConnectionWithAutoClose.java index 0fe4e251..1d3ed95a 100644 --- a/simplCore/src/ecologylab/sql/ConnectionWithAutoClose.java +++ b/simplCore/src/ecologylab/sql/ConnectionWithAutoClose.java @@ -1,105 +1,105 @@ -/** - * - */ -package ecologylab.sql; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -/** - * Wraps a java.sql.Connection object, keeping track of all of the statements it produces. On close, - * automatically closes all open connections and releases them for garbage collection. - * - * TODO Ultimately, this class should implement java.sql.Connection, but for now, it only implements - * a few select methods; adding others as needed should be straightforward. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class ConnectionWithAutoClose -{ - Connection conn; - - List stmts = null; - - public ConnectionWithAutoClose(Connection conn) - { - this.conn = conn; - } - - public PreparedStatementWithAutoClose prepareStatement(String sql) throws SQLException - { - PreparedStatement ps = conn.prepareStatement(sql); - PreparedStatementWithAutoClose psac = new PreparedStatementWithAutoClose(ps); - stmts().add(psac); - - return psac; - } - - public PreparedStatementWithAutoClose prepareStatement(String sql, int autoGeneratedKeys) throws SQLException - { - PreparedStatement ps = conn.prepareStatement(sql, autoGeneratedKeys); - PreparedStatementWithAutoClose psac = new PreparedStatementWithAutoClose(ps); - stmts().add(psac); - - return psac; - } - - public StatementWithAutoClose createStatement() throws SQLException - { - StatementWithAutoClose sac = new StatementWithAutoClose(conn.createStatement()); - stmts().add(sac); - - return sac; - } - - private List stmts() - { - if (stmts == null) - { - synchronized (this) - { - if (stmts == null) - { - stmts = new LinkedList(); - } - } - } - - return stmts; - } - - /** - * Wraps PreparedStatement.close() and eats its exceptions. Before invoking stmt.close(), closes - * all open ResultSets that were returned by this. - */ - public void close() - { - if (stmts != null) - { - Iterator stmtIter = stmts.iterator(); - - while (stmtIter.hasNext()) - { - StatementWithAutoClose stmt = stmtIter.next(); - stmtIter.remove(); - - stmt.close(); - } - } - - try - { - conn.close(); - } - catch (SQLException e) - { - } - - conn = null; - } -} +/** + * + */ +package ecologylab.sql; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +/** + * Wraps a java.sql.Connection object, keeping track of all of the statements it produces. On close, + * automatically closes all open connections and releases them for garbage collection. + * + * TODO Ultimately, this class should implement java.sql.Connection, but for now, it only implements + * a few select methods; adding others as needed should be straightforward. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class ConnectionWithAutoClose +{ + Connection conn; + + List stmts = null; + + public ConnectionWithAutoClose(Connection conn) + { + this.conn = conn; + } + + public PreparedStatementWithAutoClose prepareStatement(String sql) throws SQLException + { + PreparedStatement ps = conn.prepareStatement(sql); + PreparedStatementWithAutoClose psac = new PreparedStatementWithAutoClose(ps); + stmts().add(psac); + + return psac; + } + + public PreparedStatementWithAutoClose prepareStatement(String sql, int autoGeneratedKeys) throws SQLException + { + PreparedStatement ps = conn.prepareStatement(sql, autoGeneratedKeys); + PreparedStatementWithAutoClose psac = new PreparedStatementWithAutoClose(ps); + stmts().add(psac); + + return psac; + } + + public StatementWithAutoClose createStatement() throws SQLException + { + StatementWithAutoClose sac = new StatementWithAutoClose(conn.createStatement()); + stmts().add(sac); + + return sac; + } + + private List stmts() + { + if (stmts == null) + { + synchronized (this) + { + if (stmts == null) + { + stmts = new LinkedList(); + } + } + } + + return stmts; + } + + /** + * Wraps PreparedStatement.close() and eats its exceptions. Before invoking stmt.close(), closes + * all open ResultSets that were returned by this. + */ + public void close() + { + if (stmts != null) + { + Iterator stmtIter = stmts.iterator(); + + while (stmtIter.hasNext()) + { + StatementWithAutoClose stmt = stmtIter.next(); + stmtIter.remove(); + + stmt.close(); + } + } + + try + { + conn.close(); + } + catch (SQLException e) + { + } + + conn = null; + } +} diff --git a/simplCore/src/ecologylab/sql/PreparedStatementWithAutoClose.java b/simplCore/src/ecologylab/sql/PreparedStatementWithAutoClose.java index 2eb65f4a..22eb60f4 100644 --- a/simplCore/src/ecologylab/sql/PreparedStatementWithAutoClose.java +++ b/simplCore/src/ecologylab/sql/PreparedStatementWithAutoClose.java @@ -1,83 +1,83 @@ -/** - * - */ -package ecologylab.sql; - -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -/** - * Wraps a java.sql.PreparedStatement, tracking all of its open ResultSets. On close, automatically - * closes any open ResultSets. - * - * Used by ecologylab.sql.ConnectionWithAutoClose to wrap all prepareStatement() results. - * - * TODO Ultimately, this class should implement java.sql.PreparedStatement, but for now, it only - * implements a few select methods; adding others as needed should be straightforward. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class PreparedStatementWithAutoClose extends StatementWithAutoClose -{ - public PreparedStatementWithAutoClose(PreparedStatement stmt) - { - super(stmt); - } - - public ResultSet executeQuery() throws SQLException - { - ResultSet rs = stmt.executeQuery(); - - results().add(rs); - - return rs; - } - - public int executeUpdate() throws SQLException - { - return stmt.executeUpdate(); - } - - /** - * @param parameterIndex - * @param x - * @throws SQLException - */ - public void setLong(int parameterIndex, long x) throws SQLException - { - this.stmt.setLong(parameterIndex, x); - } - - /** - * @param parameterIndex - * @param x - * @throws SQLException - */ - public void setInt(int parameterIndex, int x) throws SQLException - { - this.stmt.setInt(parameterIndex, x); - } - - /** - * @param parameterIndex - * @param x - * @throws SQLException - */ - public void setString(int parameterIndex, String x) throws SQLException - { - this.stmt.setString(parameterIndex, x); - } - - /** - * @return - * @throws SQLException - */ - public ResultSet getGeneratedKeys() throws SQLException - { - ResultSet rs = this.stmt.getGeneratedKeys(); - results().add(rs); - - return rs; - } -} +/** + * + */ +package ecologylab.sql; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * Wraps a java.sql.PreparedStatement, tracking all of its open ResultSets. On close, automatically + * closes any open ResultSets. + * + * Used by ecologylab.sql.ConnectionWithAutoClose to wrap all prepareStatement() results. + * + * TODO Ultimately, this class should implement java.sql.PreparedStatement, but for now, it only + * implements a few select methods; adding others as needed should be straightforward. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class PreparedStatementWithAutoClose extends StatementWithAutoClose +{ + public PreparedStatementWithAutoClose(PreparedStatement stmt) + { + super(stmt); + } + + public ResultSet executeQuery() throws SQLException + { + ResultSet rs = stmt.executeQuery(); + + results().add(rs); + + return rs; + } + + public int executeUpdate() throws SQLException + { + return stmt.executeUpdate(); + } + + /** + * @param parameterIndex + * @param x + * @throws SQLException + */ + public void setLong(int parameterIndex, long x) throws SQLException + { + this.stmt.setLong(parameterIndex, x); + } + + /** + * @param parameterIndex + * @param x + * @throws SQLException + */ + public void setInt(int parameterIndex, int x) throws SQLException + { + this.stmt.setInt(parameterIndex, x); + } + + /** + * @param parameterIndex + * @param x + * @throws SQLException + */ + public void setString(int parameterIndex, String x) throws SQLException + { + this.stmt.setString(parameterIndex, x); + } + + /** + * @return + * @throws SQLException + */ + public ResultSet getGeneratedKeys() throws SQLException + { + ResultSet rs = this.stmt.getGeneratedKeys(); + results().add(rs); + + return rs; + } +} diff --git a/simplCore/src/ecologylab/sql/StatementWithAutoClose.java b/simplCore/src/ecologylab/sql/StatementWithAutoClose.java index 13b5733e..0a64da9f 100644 --- a/simplCore/src/ecologylab/sql/StatementWithAutoClose.java +++ b/simplCore/src/ecologylab/sql/StatementWithAutoClose.java @@ -1,100 +1,100 @@ -/** - * - */ -package ecologylab.sql; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -/** - * Wraps a java.sql.PreparedStatement, tracking all of its open ResultSets. On close, automatically - * closes any open ResultSets. - * - * Used by ecologylab.sql.ConnectionWithAutoClose to wrap all prepareStatement() results. - * - * TODO Ultimately, this class should implement java.sql.PreparedStatement, but for now, it only - * implements a few select methods; adding others as needed should be straightforward. - * - * @author Zachary O. Toups (zach@ecologylab.net) - */ -public class StatementWithAutoClose -{ - protected S stmt; - - protected List results = null; - - public StatementWithAutoClose(S stmt) - { - this.stmt = stmt; - } - - public ResultSet executeQuery(String sql) throws SQLException - { - ResultSet rs = stmt.executeQuery(sql); - - results().add(rs); - - return rs; - } - - public int executeUpdate(String sql) throws SQLException - { - return stmt.executeUpdate(sql); - } - - protected List results() - { - if (results == null) - { - synchronized (this) - { - if (results == null) - { - results = new LinkedList(); - } - } - } - - return results; - } - - /** - * Wraps PreparedStatement.close() and eats its exceptions. Before invoking stmt.close(), closes - * all open ResultSets that were returned by this. - */ - public void close() - { - if (results != null) - { - Iterator resultSetIterator = results.iterator(); - - while (resultSetIterator.hasNext()) - { - ResultSet resultSet = resultSetIterator.next(); - resultSetIterator.remove(); - - try - { - resultSet.close(); - } - catch (SQLException e) - { - } - } - } - - try - { - stmt.close(); - } - catch (SQLException e) - { - } - - stmt = null; - } -} +/** + * + */ +package ecologylab.sql; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +/** + * Wraps a java.sql.PreparedStatement, tracking all of its open ResultSets. On close, automatically + * closes any open ResultSets. + * + * Used by ecologylab.sql.ConnectionWithAutoClose to wrap all prepareStatement() results. + * + * TODO Ultimately, this class should implement java.sql.PreparedStatement, but for now, it only + * implements a few select methods; adding others as needed should be straightforward. + * + * @author Zachary O. Toups (zach@ecologylab.net) + */ +public class StatementWithAutoClose +{ + protected S stmt; + + protected List results = null; + + public StatementWithAutoClose(S stmt) + { + this.stmt = stmt; + } + + public ResultSet executeQuery(String sql) throws SQLException + { + ResultSet rs = stmt.executeQuery(sql); + + results().add(rs); + + return rs; + } + + public int executeUpdate(String sql) throws SQLException + { + return stmt.executeUpdate(sql); + } + + protected List results() + { + if (results == null) + { + synchronized (this) + { + if (results == null) + { + results = new LinkedList(); + } + } + } + + return results; + } + + /** + * Wraps PreparedStatement.close() and eats its exceptions. Before invoking stmt.close(), closes + * all open ResultSets that were returned by this. + */ + public void close() + { + if (results != null) + { + Iterator resultSetIterator = results.iterator(); + + while (resultSetIterator.hasNext()) + { + ResultSet resultSet = resultSetIterator.next(); + resultSetIterator.remove(); + + try + { + resultSet.close(); + } + catch (SQLException e) + { + } + } + } + + try + { + stmt.close(); + } + catch (SQLException e) + { + } + + stmt = null; + } +} diff --git a/simplCore/src/ecologylab/tests/ClassTagged.java b/simplCore/src/ecologylab/tests/ClassTagged.java index c86334b7..bf992930 100644 --- a/simplCore/src/ecologylab/tests/ClassTagged.java +++ b/simplCore/src/ecologylab/tests/ClassTagged.java @@ -1,28 +1,28 @@ -/** - * - */ -package ecologylab.tests; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public @simpl_tag("CLASS_NAME_TAG") class ClassTagged extends ElementState -{ - @simpl_scalar @simpl_tag("BLARG") String blarg = null; - @simpl_composite @simpl_tag("ASDF:NU") FieldTagged fieldTagged = new FieldTagged(); - - /** - * - */ - public ClassTagged() - { - blarg = "blarg"; - } - -} +/** + * + */ +package ecologylab.tests; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public @simpl_tag("CLASS_NAME_TAG") class ClassTagged extends ElementState +{ + @simpl_scalar @simpl_tag("BLARG") String blarg = null; + @simpl_composite @simpl_tag("ASDF:NU") FieldTagged fieldTagged = new FieldTagged(); + + /** + * + */ + public ClassTagged() + { + blarg = "blarg"; + } + +} diff --git a/simplCore/src/ecologylab/tests/Composed.java b/simplCore/src/ecologylab/tests/Composed.java index f835c66c..0fa6c9bc 100644 --- a/simplCore/src/ecologylab/tests/Composed.java +++ b/simplCore/src/ecologylab/tests/Composed.java @@ -1,62 +1,62 @@ -/** - * - */ -package ecologylab.tests; - -import java.util.ArrayList; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -@simpl_tag("fred:flintstone") -public class Composed extends ElementState -{ - @simpl_collection("ClassTagged") - ArrayList tagged = new ArrayList(); - - @simpl_scalar - int x = 22; - - /** - * - */ - public Composed() - { - tagged.add(new ClassTagged()); - tagged.add(new ClassTagged()); - tagged.add(new ClassTagged()); - } - - static final Class[] classes = - { Composed.class, ClassTagged.class, FieldTagged.class }; - - public static void main(String[] args) throws SIMPLTranslationException - { - SimplTypesScope ts = SimplTypesScope.get("testXMLTag", classes); - - Composed c = new Composed(); - - final StringBuilder translatedXML = SimplTypesScope.serialize(c, StringFormat.XML); - - System.out.println(translatedXML); - - Composed retranslated = (Composed) ts.deserialize(translatedXML, StringFormat.XML); - // Composed retranslated = (Composed) ElementState.translateFromXMLSAX(translatedXML, ts); - - SimplTypesScope.serialize(c, System.out, StringFormat.XML); - System.out.println("\n\nretranslated:"); - - SimplTypesScope.serialize(retranslated, System.out, StringFormat.XML); - // retranslated.translateToXML(System.out); - } - -} +/** + * + */ +package ecologylab.tests; + +import java.util.ArrayList; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +@simpl_tag("fred:flintstone") +public class Composed extends ElementState +{ + @simpl_collection("ClassTagged") + ArrayList tagged = new ArrayList(); + + @simpl_scalar + int x = 22; + + /** + * + */ + public Composed() + { + tagged.add(new ClassTagged()); + tagged.add(new ClassTagged()); + tagged.add(new ClassTagged()); + } + + static final Class[] classes = + { Composed.class, ClassTagged.class, FieldTagged.class }; + + public static void main(String[] args) throws SIMPLTranslationException + { + SimplTypesScope ts = SimplTypesScope.get("testXMLTag", classes); + + Composed c = new Composed(); + + final StringBuilder translatedXML = SimplTypesScope.serialize(c, StringFormat.XML); + + System.out.println(translatedXML); + + Composed retranslated = (Composed) ts.deserialize(translatedXML, StringFormat.XML); + // Composed retranslated = (Composed) ElementState.translateFromXMLSAX(translatedXML, ts); + + SimplTypesScope.serialize(c, System.out, StringFormat.XML); + System.out.println("\n\nretranslated:"); + + SimplTypesScope.serialize(retranslated, System.out, StringFormat.XML); + // retranslated.translateToXML(System.out); + } + +} diff --git a/simplCore/src/ecologylab/tests/FieldTagged.java b/simplCore/src/ecologylab/tests/FieldTagged.java index d88cdf36..e8a6d64e 100644 --- a/simplCore/src/ecologylab/tests/FieldTagged.java +++ b/simplCore/src/ecologylab/tests/FieldTagged.java @@ -1,24 +1,24 @@ -/** - * - */ -package ecologylab.tests; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class FieldTagged extends ElementState -{ - @simpl_scalar int x = 37; - /** - * - */ - public FieldTagged() - { - // TODO Auto-generated constructor stub - } - -} +/** + * + */ +package ecologylab.tests; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class FieldTagged extends ElementState +{ + @simpl_scalar int x = 37; + /** + * + */ + public FieldTagged() + { + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/tests/TestClient.java b/simplCore/src/ecologylab/tests/TestClient.java index 6354f82e..42a551c8 100644 --- a/simplCore/src/ecologylab/tests/TestClient.java +++ b/simplCore/src/ecologylab/tests/TestClient.java @@ -1,32 +1,32 @@ -/** - * - */ -package ecologylab.tests; - -import java.io.IOException; -import java.net.BindException; -import java.net.UnknownHostException; - -import ecologylab.oodss.distributed.client.NIOClient; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class TestClient -{ - - /** - * @param args - * @throws IOException - * @throws UnknownHostException - * @throws BindException - */ - public static void main(String[] args) throws BindException, UnknownHostException, IOException - { - NIOClient c = new NIOClient("localhost", 14444, null, null); - - c.connect(); - } - -} +/** + * + */ +package ecologylab.tests; + +import java.io.IOException; +import java.net.BindException; +import java.net.UnknownHostException; + +import ecologylab.oodss.distributed.client.NIOClient; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class TestClient +{ + + /** + * @param args + * @throws IOException + * @throws UnknownHostException + * @throws BindException + */ + public static void main(String[] args) throws BindException, UnknownHostException, IOException + { + NIOClient c = new NIOClient("localhost", 14444, null, null); + + c.connect(); + } + +} diff --git a/simplCore/src/ecologylab/tests/TestScalarCollection.java b/simplCore/src/ecologylab/tests/TestScalarCollection.java index 9e47bc37..d93c2d18 100644 --- a/simplCore/src/ecologylab/tests/TestScalarCollection.java +++ b/simplCore/src/ecologylab/tests/TestScalarCollection.java @@ -1,47 +1,47 @@ -/** - * - */ -package ecologylab.tests; - -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * - * @author andruid - */ -public class TestScalarCollection extends ElementState -{ - @simpl_nowrap - @simpl_collection("person") - ArrayList stuff; - - @simpl_nowrap - @simpl_collection("link") - ArrayList purls; - - static final SimplTypesScope TS = SimplTypesScope.get("test_scalar", null, - TestScalarCollection.class); - - static final String xml = "fredwilmahttp://www.google.comhttp://ecologylab.cs.tamu.edu"; - - public static void main(String[] a) - { - try - { - Object es = TS.deserialize(xml, StringFormat.XML); - SimplTypesScope.serialize(es, System.out, StringFormat.XML); - } - catch (SIMPLTranslationException e) - { - e.printStackTrace(); - } - } -} +/** + * + */ +package ecologylab.tests; + +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * + * @author andruid + */ +public class TestScalarCollection extends ElementState +{ + @simpl_nowrap + @simpl_collection("person") + ArrayList stuff; + + @simpl_nowrap + @simpl_collection("link") + ArrayList purls; + + static final SimplTypesScope TS = SimplTypesScope.get("test_scalar", null, + TestScalarCollection.class); + + static final String xml = "fredwilmahttp://www.google.comhttp://ecologylab.cs.tamu.edu"; + + public static void main(String[] a) + { + try + { + Object es = TS.deserialize(xml, StringFormat.XML); + SimplTypesScope.serialize(es, System.out, StringFormat.XML); + } + catch (SIMPLTranslationException e) + { + e.printStackTrace(); + } + } +} diff --git a/simplCore/src/ecologylab/tests/TestServer.java b/simplCore/src/ecologylab/tests/TestServer.java index e422b310..46d6f23b 100644 --- a/simplCore/src/ecologylab/tests/TestServer.java +++ b/simplCore/src/ecologylab/tests/TestServer.java @@ -1,41 +1,41 @@ -/** - * - */ -package ecologylab.tests; - -import java.io.IOException; -import java.net.BindException; -import java.net.UnknownHostException; - -import ecologylab.generic.Debug; -import ecologylab.net.NetTools; -import ecologylab.oodss.distributed.client.NIOClient; -import ecologylab.oodss.distributed.server.DoubleThreadedNIOServer; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class TestServer -{ - - /** - * @param args - * @throws IOException - * @throws UnknownHostException - * @throws BindException - */ - public static void main(String[] args) throws BindException, UnknownHostException, IOException - { - DoubleThreadedNIOServer s = DoubleThreadedNIOServer.getInstance(14444, NetTools.getAllInetAddressesForLocalhost(), null, null, 11111111, 1111111111); - - s.start(); - - NIOClient c = new NIOClient("localhost", 14444, null, null); - - Debug.println("------------------------------------ Start connect."); - c.connect(); - Debug.println("------------------------------------ connect returned."); - } - -} +/** + * + */ +package ecologylab.tests; + +import java.io.IOException; +import java.net.BindException; +import java.net.UnknownHostException; + +import ecologylab.generic.Debug; +import ecologylab.net.NetTools; +import ecologylab.oodss.distributed.client.NIOClient; +import ecologylab.oodss.distributed.server.DoubleThreadedNIOServer; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class TestServer +{ + + /** + * @param args + * @throws IOException + * @throws UnknownHostException + * @throws BindException + */ + public static void main(String[] args) throws BindException, UnknownHostException, IOException + { + DoubleThreadedNIOServer s = DoubleThreadedNIOServer.getInstance(14444, NetTools.getAllInetAddressesForLocalhost(), null, null, 11111111, 1111111111); + + s.start(); + + NIOClient c = new NIOClient("localhost", 14444, null, null); + + Debug.println("------------------------------------ Start connect."); + c.connect(); + Debug.println("------------------------------------ connect returned."); + } + +} diff --git a/simplCore/src/ecologylab/tests/TestXMLFormat.java b/simplCore/src/ecologylab/tests/TestXMLFormat.java index d1e5461d..2add33b4 100644 --- a/simplCore/src/ecologylab/tests/TestXMLFormat.java +++ b/simplCore/src/ecologylab/tests/TestXMLFormat.java @@ -1,59 +1,59 @@ -/** - * - */ -package ecologylab.tests; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_format; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - * - */ -public class TestXMLFormat extends ElementState -{ - @simpl_scalar - @simpl_format("#") - double decimal0 = 1.654654654654645321321; - - @simpl_scalar - @simpl_format("#.#") - double decimal1 = -1.654654654654645321321; - - @simpl_scalar - @simpl_format("#.0#") - double decimal2 = -11111.654654654654645321321; - - @simpl_scalar - @simpl_format("#.###") - double decimal3 = 0.654654654654645321321; - - public TestXMLFormat() - { - - } - - /** - * @param args - * @throws SIMPLTranslationException - */ - public static void main(String[] args) throws SIMPLTranslationException - { - TestXMLFormat t = new TestXMLFormat(); - - SimplTypesScope.serialize(t, System.out, StringFormat.XML); - - System.out.println(); - - SimplTypesScope translationScope = SimplTypesScope.get("test", TestXMLFormat.class); - SimplTypesScope.serialize(translationScope.deserialize(SimplTypesScope.serialize(t, - StringFormat.XML).toString(), StringFormat.XML), System.out, StringFormat.XML); - System.out.println(); - - System.out.println(SimplTypesScope.serialize(t, StringFormat.XML)); - } -} +/** + * + */ +package ecologylab.tests; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_format; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + * + */ +public class TestXMLFormat extends ElementState +{ + @simpl_scalar + @simpl_format("#") + double decimal0 = 1.654654654654645321321; + + @simpl_scalar + @simpl_format("#.#") + double decimal1 = -1.654654654654645321321; + + @simpl_scalar + @simpl_format("#.0#") + double decimal2 = -11111.654654654654645321321; + + @simpl_scalar + @simpl_format("#.###") + double decimal3 = 0.654654654654645321321; + + public TestXMLFormat() + { + + } + + /** + * @param args + * @throws SIMPLTranslationException + */ + public static void main(String[] args) throws SIMPLTranslationException + { + TestXMLFormat t = new TestXMLFormat(); + + SimplTypesScope.serialize(t, System.out, StringFormat.XML); + + System.out.println(); + + SimplTypesScope translationScope = SimplTypesScope.get("test", TestXMLFormat.class); + SimplTypesScope.serialize(translationScope.deserialize(SimplTypesScope.serialize(t, + StringFormat.XML).toString(), StringFormat.XML), System.out, StringFormat.XML); + System.out.println(); + + System.out.println(SimplTypesScope.serialize(t, StringFormat.XML)); + } +} diff --git a/simplCore/src/ecologylab/tests/package.html b/simplCore/src/ecologylab/tests/package.html index 14d68a13..3da9bd39 100644 --- a/simplCore/src/ecologylab/tests/package.html +++ b/simplCore/src/ecologylab/tests/package.html @@ -1,3 +1,3 @@ - -Stand-alone applications for testing Interface Ecology Lab Fundamental components. - + +Stand-alone applications for testing Interface Ecology Lab Fundamental components. + diff --git a/simplCore/src/ecologylab/tests/serialization/Base.java b/simplCore/src/ecologylab/tests/serialization/Base.java index bf770d96..426fca2e 100644 --- a/simplCore/src/ecologylab/tests/serialization/Base.java +++ b/simplCore/src/ecologylab/tests/serialization/Base.java @@ -1,34 +1,34 @@ -/** - * - */ -package ecologylab.tests.serialization; - -import java.util.ArrayList; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_scope; - -/** - * @author andruid - * - */ -public class Base extends ElementState -{ - - @simpl_scope(RssPolyWrapTest.POLY_WRAP_TEST_TRANSLATIONS_NAME) - @simpl_collection - ArrayList mixins; - - public static final SimplTypesScope BASE_TRANSLATIONS = - SimplTypesScope.get("base_translations", Base.class); - /** - * - */ - public Base() - { - // TODO Auto-generated constructor stub - } - -} +/** + * + */ +package ecologylab.tests.serialization; + +import java.util.ArrayList; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_scope; + +/** + * @author andruid + * + */ +public class Base extends ElementState +{ + + @simpl_scope(RssPolyWrapTest.POLY_WRAP_TEST_TRANSLATIONS_NAME) + @simpl_collection + ArrayList mixins; + + public static final SimplTypesScope BASE_TRANSLATIONS = + SimplTypesScope.get("base_translations", Base.class); + /** + * + */ + public Base() + { + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/tests/serialization/ChannelTest.java b/simplCore/src/ecologylab/tests/serialization/ChannelTest.java index 55044f9a..7dd41cb8 100644 --- a/simplCore/src/ecologylab/tests/serialization/ChannelTest.java +++ b/simplCore/src/ecologylab/tests/serialization/ChannelTest.java @@ -1,20 +1,20 @@ -package ecologylab.tests.serialization; - -import java.util.ArrayList; - -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.library.rss.Item; - -@simpl_tag("channel") -public class ChannelTest extends Base -{ - @simpl_nowrap @simpl_collection("item") ArrayList items; - - public ChannelTest() - { - // TODO Auto-generated constructor stub - } - -} +package ecologylab.tests.serialization; + +import java.util.ArrayList; + +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.library.rss.Item; + +@simpl_tag("channel") +public class ChannelTest extends Base +{ + @simpl_nowrap @simpl_collection("item") ArrayList items; + + public ChannelTest() + { + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/tests/serialization/ItemTest.java b/simplCore/src/ecologylab/tests/serialization/ItemTest.java index fb228a0c..517bd91b 100644 --- a/simplCore/src/ecologylab/tests/serialization/ItemTest.java +++ b/simplCore/src/ecologylab/tests/serialization/ItemTest.java @@ -1,38 +1,38 @@ -/** - * - */ -package ecologylab.tests.serialization; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -/** - * @author andruid - * - */ -@simpl_tag("item") -public class ItemTest extends Base -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; - /** - * This version of link often has a special url with rss in it. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; - /** - * This seems to be the version of link that users want to see. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL guid; - - /** - * - */ - public ItemTest() - { - // TODO Auto-generated constructor stub - } - -} +/** + * + */ +package ecologylab.tests.serialization; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +/** + * @author andruid + * + */ +@simpl_tag("item") +public class ItemTest extends Base +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; + /** + * This version of link often has a special url with rss in it. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; + /** + * This seems to be the version of link that users want to see. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL guid; + + /** + * + */ + public ItemTest() + { + // TODO Auto-generated constructor stub + } + +} diff --git a/simplCore/src/ecologylab/tests/serialization/RssPolyWrapTest.java b/simplCore/src/ecologylab/tests/serialization/RssPolyWrapTest.java index ce054390..33e8fac3 100644 --- a/simplCore/src/ecologylab/tests/serialization/RssPolyWrapTest.java +++ b/simplCore/src/ecologylab/tests/serialization/RssPolyWrapTest.java @@ -1,60 +1,60 @@ -/** - * - */ -package ecologylab.tests.serialization; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_tag; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * @author andruid - * - */ -@simpl_tag("rss") -public class RssPolyWrapTest extends Base -{ - @simpl_composite - ChannelTest channel; - - public static final String POLY_WRAP_TEST_TRANSLATIONS_NAME = "poly_wrap_test_translations"; - - public static final SimplTypesScope POLY_WRAP_TEST_TRANSLATIONS = SimplTypesScope.get(POLY_WRAP_TEST_TRANSLATIONS_NAME, - Base.BASE_TRANSLATIONS, - RssPolyWrapTest.class, - ChannelTest.class, - ItemTest.class); - - public static final ParsedURL BUZZ_SPORTS = ParsedURL.getAbsolute("http://buzzlog.yahoo.com/feeds/buzzsportm.xml"); - - /** - * - */ - public RssPolyWrapTest() - { - - } - - public static void main(String[] args) - { - try - { - Object result = POLY_WRAP_TEST_TRANSLATIONS.deserialize(BUZZ_SPORTS, Format.XML); - System.out.println('\n'); - SimplTypesScope.serialize(result, System.out, StringFormat.XML); - - System.out.println('\n'); - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - System.out.println("\n"); - } - -} +/** + * + */ +package ecologylab.tests.serialization; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_tag; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * @author andruid + * + */ +@simpl_tag("rss") +public class RssPolyWrapTest extends Base +{ + @simpl_composite + ChannelTest channel; + + public static final String POLY_WRAP_TEST_TRANSLATIONS_NAME = "poly_wrap_test_translations"; + + public static final SimplTypesScope POLY_WRAP_TEST_TRANSLATIONS = SimplTypesScope.get(POLY_WRAP_TEST_TRANSLATIONS_NAME, + Base.BASE_TRANSLATIONS, + RssPolyWrapTest.class, + ChannelTest.class, + ItemTest.class); + + public static final ParsedURL BUZZ_SPORTS = ParsedURL.getAbsolute("http://buzzlog.yahoo.com/feeds/buzzsportm.xml"); + + /** + * + */ + public RssPolyWrapTest() + { + + } + + public static void main(String[] args) + { + try + { + Object result = POLY_WRAP_TEST_TRANSLATIONS.deserialize(BUZZ_SPORTS, Format.XML); + System.out.println('\n'); + SimplTypesScope.serialize(result, System.out, StringFormat.XML); + + System.out.println('\n'); + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + System.out.println("\n"); + } + +} diff --git a/simplCore/src/ecologylab/textformat/NamedStyle.java b/simplCore/src/ecologylab/textformat/NamedStyle.java index f0e8c154..5e8bd91c 100644 --- a/simplCore/src/ecologylab/textformat/NamedStyle.java +++ b/simplCore/src/ecologylab/textformat/NamedStyle.java @@ -1,190 +1,190 @@ -package ecologylab.textformat; - -import ecologylab.appframework.types.prefs.Pref; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.element.IMappable; - -/** - * Set of variables that control the font style. May contain a name. - * A Map State of named stles is stored in AWTBridge. - * @author alexgrau - */ -@simpl_inherit -public class NamedStyle extends ElementState -implements IMappable -{ - public static final int STROKE_RECTANGLE_FIT = 0; - public static final int STROKE_SMOOTH_FIT = 1; - public static final int STROKE_RECTANGLE = 2; - public static final int STROKE_NONE = 3; - - /** Name for this given style */ - @simpl_scalar - protected String name; - - /** Boolean indicating whether to underline the entire chunk or not */ - @simpl_scalar - protected boolean underline; - - /** Integer indicating the size of the chunk font */ - @simpl_scalar - protected int fontSize; - - /** Integer indicating the alignment */ - @simpl_scalar - protected int alignment; - - /** Integer indicating the faceIndex of the chunk */ - @simpl_scalar - protected int faceIndex; - - /** Integer indicating the fontStyle of the chunk. Follows Font constants. */ - @simpl_scalar - protected int fontStyle; - - /** Integer that indicates the stroke style for this chunk */ - @simpl_scalar - protected int strokeStyle = Pref.lookupInt("stroke_style", STROKE_RECTANGLE_FIT); - - private long ormId; - - /** - * Set of variables that control the font style. May contain a name. - * A Map State of named stles is stored in AWTBridge. - */ - public NamedStyle(){} - - - public NamedStyle(int fontSize) - { - this.fontSize = fontSize; - } - - public NamedStyle(int fontSize, int strokeStyle) - { - this.fontSize = fontSize; - this.strokeStyle = strokeStyle; - } - - /** - * Set of variables that control the font style. May contain a name. - * A Map State of named stles is stored in AWTBridge. - */ - public NamedStyle(String name, boolean underline, int fontSize, int alignment, int faceIndex, int fontStyle) - { - this.name = name; - this.underline = underline; - this.fontSize = fontSize; - this.alignment = alignment; - this.faceIndex = faceIndex; - this.fontStyle = fontStyle; - } - - /** - * Set of variables that control the font style. May contain a name. - * A Map State of named stles is stored in AWTBridge. - */ - public NamedStyle(String name, boolean underline, int fontSize, int alignment, int faceIndex, int fontStyle, int strokeStyle) - { - this( name, underline, fontSize, alignment, faceIndex, fontStyle); - this.strokeStyle = strokeStyle; - } - - - public String getName() - { - return name; - } - - public void setName(String name) - { - this.name = name; - } - - public boolean getUnderline() - { - return underline; - } - - public void setUnderline(boolean underline) - { - this.underline = underline; - } - - public int getFontSize() - { - return fontSize; - } - - public void setFontSize(int fontSize) - { - this.fontSize = fontSize; - } - - public int getAlignment() - { - return alignment; - } - - public void setAlignment(int alignment) - { - this.alignment = alignment; - } - - public int getFaceIndex() - { - return faceIndex; - } - - public void setFaceIndex(int faceIndex) - { - this.faceIndex = faceIndex; - } - - public int getFontStyle() - { - return fontStyle; - } - - public void setFontStyle(int fontStyle) - { - this.fontStyle = fontStyle; - } - - public int getStrokeStyle() - { - return strokeStyle; - } - - public void setStrokeStyle(int strokeStyle) - { - this.strokeStyle = strokeStyle; - } - - @Override - public void recycle() - { - name = null; - super.recycle(); - } - - @Override - public String key() - { - return name; - } - - - public long getOrmId() - { - return ormId; - } - - - public void setOrmId(long ormId) - { - this.ormId = ormId; - } -} +package ecologylab.textformat; + +import ecologylab.appframework.types.prefs.Pref; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.element.IMappable; + +/** + * Set of variables that control the font style. May contain a name. + * A Map State of named stles is stored in AWTBridge. + * @author alexgrau + */ +@simpl_inherit +public class NamedStyle extends ElementState +implements IMappable +{ + public static final int STROKE_RECTANGLE_FIT = 0; + public static final int STROKE_SMOOTH_FIT = 1; + public static final int STROKE_RECTANGLE = 2; + public static final int STROKE_NONE = 3; + + /** Name for this given style */ + @simpl_scalar + protected String name; + + /** Boolean indicating whether to underline the entire chunk or not */ + @simpl_scalar + protected boolean underline; + + /** Integer indicating the size of the chunk font */ + @simpl_scalar + protected int fontSize; + + /** Integer indicating the alignment */ + @simpl_scalar + protected int alignment; + + /** Integer indicating the faceIndex of the chunk */ + @simpl_scalar + protected int faceIndex; + + /** Integer indicating the fontStyle of the chunk. Follows Font constants. */ + @simpl_scalar + protected int fontStyle; + + /** Integer that indicates the stroke style for this chunk */ + @simpl_scalar + protected int strokeStyle = Pref.lookupInt("stroke_style", STROKE_RECTANGLE_FIT); + + private long ormId; + + /** + * Set of variables that control the font style. May contain a name. + * A Map State of named stles is stored in AWTBridge. + */ + public NamedStyle(){} + + + public NamedStyle(int fontSize) + { + this.fontSize = fontSize; + } + + public NamedStyle(int fontSize, int strokeStyle) + { + this.fontSize = fontSize; + this.strokeStyle = strokeStyle; + } + + /** + * Set of variables that control the font style. May contain a name. + * A Map State of named stles is stored in AWTBridge. + */ + public NamedStyle(String name, boolean underline, int fontSize, int alignment, int faceIndex, int fontStyle) + { + this.name = name; + this.underline = underline; + this.fontSize = fontSize; + this.alignment = alignment; + this.faceIndex = faceIndex; + this.fontStyle = fontStyle; + } + + /** + * Set of variables that control the font style. May contain a name. + * A Map State of named stles is stored in AWTBridge. + */ + public NamedStyle(String name, boolean underline, int fontSize, int alignment, int faceIndex, int fontStyle, int strokeStyle) + { + this( name, underline, fontSize, alignment, faceIndex, fontStyle); + this.strokeStyle = strokeStyle; + } + + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public boolean getUnderline() + { + return underline; + } + + public void setUnderline(boolean underline) + { + this.underline = underline; + } + + public int getFontSize() + { + return fontSize; + } + + public void setFontSize(int fontSize) + { + this.fontSize = fontSize; + } + + public int getAlignment() + { + return alignment; + } + + public void setAlignment(int alignment) + { + this.alignment = alignment; + } + + public int getFaceIndex() + { + return faceIndex; + } + + public void setFaceIndex(int faceIndex) + { + this.faceIndex = faceIndex; + } + + public int getFontStyle() + { + return fontStyle; + } + + public void setFontStyle(int fontStyle) + { + this.fontStyle = fontStyle; + } + + public int getStrokeStyle() + { + return strokeStyle; + } + + public void setStrokeStyle(int strokeStyle) + { + this.strokeStyle = strokeStyle; + } + + @Override + public void recycle() + { + name = null; + super.recycle(); + } + + @Override + public String key() + { + return name; + } + + + public long getOrmId() + { + return ormId; + } + + + public void setOrmId(long ormId) + { + this.ormId = ormId; + } +} diff --git a/simplCore/src/simpl/descriptors/ParameterDescriptor.java b/simplCore/src/simpl/descriptors/ParameterDescriptor.java index a9ac507b..1acbbb87 100644 --- a/simplCore/src/simpl/descriptors/ParameterDescriptor.java +++ b/simplCore/src/simpl/descriptors/ParameterDescriptor.java @@ -1,25 +1,25 @@ -package simpl.descriptors; - -public class ParameterDescriptor { - - public boolean isAttributeParameter() { - // TODO Auto-generated method stub - return false; - } - - public Object getParameterValue() { - // TODO Auto-generated method stub - return null; - } - - public String getParameterName() { - // TODO Auto-generated method stub - return null; - } - - public boolean isMethodParameter() { - // TODO Auto-generated method stub - return false; - } - -} +package simpl.descriptors; + +public class ParameterDescriptor { + + public boolean isAttributeParameter() { + // TODO Auto-generated method stub + return false; + } + + public Object getParameterValue() { + // TODO Auto-generated method stub + return null; + } + + public String getParameterName() { + // TODO Auto-generated method stub + return null; + } + + public boolean isMethodParameter() { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/simplCore/test/ecologylab/net/TestParsedURL.java b/simplCore/test/ecologylab/net/TestParsedURL.java new file mode 100644 index 00000000..3fea7c62 --- /dev/null +++ b/simplCore/test/ecologylab/net/TestParsedURL.java @@ -0,0 +1,45 @@ +package ecologylab.net; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.junit.Assert; +import org.junit.Test; + +/** + * + * @author quyin + */ +public class TestParsedURL +{ + + @Test + public void testFragment() throws MalformedURLException + { + String u1 = "http://example.com/index.html?a=foo&b=bla#bar"; + + ParsedURL purl1 = new ParsedURL(new URL(u1)); + Assert.assertEquals("example.com", purl1.domain()); + Assert.assertEquals("/index.html", purl1.pathNoQuery()); + Assert.assertEquals("a=foo&b=bla", purl1.query()); + Assert.assertEquals("bar", purl1.fragment()); + Assert.assertEquals("http://example.com/index.html?a=foo&b=bla#bar", purl1.toString()); + + String u2 = "http://example.com/intro.html#overview"; + ParsedURL purl2 = ParsedURL.getAbsolute(u2); + Assert.assertEquals("example.com", purl2.domain()); + Assert.assertEquals("/intro.html", purl2.pathNoQuery()); + Assert.assertNull(purl2.query()); + Assert.assertEquals("overview", purl2.fragment()); + Assert.assertEquals("http://example.com/intro.html#overview", purl2.toString()); + + String relPath = "baz/search.html?q=sometext#frag"; + ParsedURL purl3 = ParsedURL.getRelative(new URL(u1), relPath, "ParsedURL.getRelative()"); + Assert.assertEquals("example.com", purl3.domain()); + Assert.assertEquals("/baz/search.html", purl3.pathNoQuery()); + Assert.assertEquals("q=sometext", purl3.query()); + Assert.assertEquals("frag", purl3.fragment()); + Assert.assertEquals("http://example.com/baz/search.html?q=sometext#frag", purl3.toString()); + } + +} diff --git a/simplCore/test/ecologylab/serialization/EnumerationDescriptionTest.java b/simplCore/test/ecologylab/serialization/EnumerationDescriptionTest.java index e08b4184..18fc4e4b 100644 --- a/simplCore/test/ecologylab/serialization/EnumerationDescriptionTest.java +++ b/simplCore/test/ecologylab/serialization/EnumerationDescriptionTest.java @@ -1,182 +1,182 @@ -package ecologylab.serialization; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class EnumerationDescriptionTest { - - @Test(expected=SIMPLDescriptionException.class) - public void descriptionsForNonEnumTypesProvokeException() throws SIMPLDescriptionException - { - EnumerationDescriptor invalid = EnumerationDescriptor.get(ClassDescriptor.class); - } - - @Test - public void descriptionForBasicEnumerationsWorks() throws SIMPLDescriptionException { - EnumerationDescriptor ed = EnumerationDescriptor.get(primaryScenarioEnum.class); - - assertTrue("There is no information about this enum", ed.metaInfo.isEmpty()); - assertTrue("There are no other tags for this enum", ed.otherTags.isEmpty()); - - assertEquals("The packageName must be correct" , primaryScenarioEnum.class.getPackage().getName(), ed.getPackageName()); - assertEquals("The javaName must be correct", primaryScenarioEnum.class.getName(), ed.getJavaTypeName()); - assertEquals("The Simpl name must be correct", "primaryScenarioEnum", ed.getName()); - - assertEquals("There should be three entries for this enum", 3, ed.getEnumerationEntries().size()); - - assertTrue("Should contain all of the values of the enum! Missing first", ed.containsEntry("firstValue")); - assertTrue("Should contain all of the values of the enum! Missing second", ed.containsEntry("secondValue")); - assertTrue("Should contain all of the values of the enum! Missing third", ed.containsEntry("thirdValue")); - assertFalse("Should not contain a value that isn't in the enum! There are no Jibbles here!", ed.containsEntry("jibbles")); - assertFalse("Should be case sensitive! FIRSTENTRY ignores casing.", ed.containsEntry("FIRSTENTRY")); - - assertEquals("Should fetch the correct enumeration value; expected firstValue", primaryScenarioEnum.firstValue, ed.getEntryEnumValue("firstValue")); - assertEquals("Should fetch the correct enumeration value; expected secondValue", primaryScenarioEnum.secondValue, ed.getEntryEnumValue("secondValue")); - assertEquals("Should fetch the correct enumeration value; expected thirdValue", primaryScenarioEnum.thirdValue, ed.getEntryEnumValue("thirdValue")); - } - - /** - * This handles some of the validations that should apply for most of the test cases; - * these have been copy pasted from the prior test case so they can be reused... - * I could have refactored this in the first test case to a method call, but I felt it was nicer w/ the core assumptions there. - * @param ed - */ - private void performBasicValidations(Class enumClass, EnumerationDescriptor ed) - { - assertTrue("There is no information about this enum", ed.metaInfo.isEmpty()); - assertTrue("There are no other tags for this enum", ed.otherTags.isEmpty()); - - assertEquals("The packageName must be correct" , enumClass.getPackage().getName(), ed.getPackageName()); - assertEquals("The javaName must be correct", enumClass.getName(), ed.getJavaTypeName()); - assertEquals("The Simpl name must be correct", enumClass.getSimpleName(), ed.getName()); - - assertEquals("There should be three entries for this enum", 3, ed.getEnumerationEntries().size()); - - assertTrue("Should contain all of the values of the enum! Missing first", ed.containsEntry("firstValue")); - assertTrue("Should contain all of the values of the enum! Missing second", ed.containsEntry("secondValue")); - assertTrue("Should contain all of the values of the enum! Missing third", ed.containsEntry("thirdValue")); - assertFalse("Should not contain a value that isn't in the enum! There are no Jibbles here!", ed.containsEntry("jibbles")); - assertFalse("Should be case sensitive! FIRSTENTRY ignores casing.", ed.containsEntry("FIRSTENTRY")); - } - - @Test(expected=SIMPLDescriptionException.class) - public void descriptionForCustomValuedEnumerationsWithoutASimplFieldProvokesException() throws SIMPLDescriptionException - { - EnumerationDescriptor invalid = EnumerationDescriptor.get(invalidEnumExample.class); - } - - @Test(expected=SIMPLDescriptionException.class) - public void descriptionForCustomValuedEnumerationsWithInvalidSimplFieldTypesProvokesException() throws SIMPLDescriptionException - { - EnumerationDescriptor invalid = EnumerationDescriptor.get(secondaryScenarioRejectsNonIntegers.class); - } - - @Test - public void customValuedEnumerartionsAreCorrectlyIdentified() - { - // Valid "custom valued" enumerations should, of course, be identified as such - assertTrue(EnumerationDescriptor.isCustomValuedEnum(secondaryScenarioEnum.class)); - assertTrue(EnumerationDescriptor.isCustomValuedEnum(secondaryScenarioAlsoSupportsPrimitiveIntEnum.class)); - - // Invalid "custom valued" enumerations (due to typing issues / lack of simpl_scalar) should be identified as "custom valued" - // so that other description code can through the appropriate exceptions - assertTrue(EnumerationDescriptor.isCustomValuedEnum(secondaryScenarioRejectsNonIntegers.class)); - - // Standard enumerations (like the basic scenario) should NOT be considered custom valued... - // Because, duh, they're not. - assertFalse("This enumeration has no custom values.", EnumerationDescriptor.isCustomValuedEnum(primaryScenarioEnum.class)); - - - // Things that are not enums are also, very obviously, not Custom Valued enumerations - assertFalse(EnumerationDescriptor.isCustomValuedEnum(String.class)); - } - - @Test - public void descriptionForCustomValuedEnumerationsWorks() throws SIMPLDescriptionException { - - EnumerationDescriptor ed = EnumerationDescriptor.get(secondaryScenarioEnum.class); - performBasicValidations(secondaryScenarioEnum.class, ed); - - // let's get the core first, then do some value marshalling. ;P - assertEquals(new Integer(3), ed.getEntryEnumIntegerValue("firstValue")); - assertEquals(new Integer(5), ed.getEntryEnumIntegerValue("secondValue")); - assertEquals(new Integer(7), ed.getEntryEnumIntegerValue("thirdValue")); - - EnumerationDescriptor secondStyle = EnumerationDescriptor.get(secondaryScenarioAlsoSupportsPrimitiveIntEnum.class); - performBasicValidations(secondaryScenarioAlsoSupportsPrimitiveIntEnum.class, secondStyle); - performValueValidation(secondStyle); - } - - private void performValueValidation(EnumerationDescriptor ed) - { - assertEquals(new Integer(3), ed.getEntryEnumIntegerValue("firstValue")); - assertEquals(new Integer(5), ed.getEntryEnumIntegerValue("secondValue")); - assertEquals(new Integer(7), ed.getEntryEnumIntegerValue("thirdValue")); - - assertEquals("firstValue", ed.getEntryEnumFromValue(3).toString()); - assertEquals("secondValue", ed.getEntryEnumFromValue(5).toString()); - assertEquals("thirdValue", ed.getEntryEnumFromValue(7).toString()); - - } - - @Test - public void enumerationDescriptionMarshalsValuesCorrectlyForNormalEnums() throws SIMPLDescriptionException, SIMPLTranslationException - { - // This is like, the simplest case. If this goes wrong, tears and shame should be part of the fix. - EnumerationDescriptor ed = EnumerationDescriptor.get(primaryScenarioEnum.class); - assertEquals("firstValue", ed.marshal(primaryScenarioEnum.firstValue)); - assertEquals("secondValue", ed.marshal(primaryScenarioEnum.secondValue)); - } - - @Test - public void enumerationDescriptionMarshalsValuesForCustomValuedEnums() throws SIMPLTranslationException, SIMPLDescriptionException - { - // This is like, the simplest case. If this goes wrong, tears and shame should be part of the fix. - EnumerationDescriptor ed = EnumerationDescriptor.get(secondaryScenarioEnum.class); - assertEquals("firstValue", ed.marshal(secondaryScenarioEnum.firstValue)); - assertEquals("secondValue", ed.marshal(secondaryScenarioEnum.secondValue)); - // Yes. This test was basically copy pasted. - } - - - @Test(expected=SIMPLTranslationException.class) - public void enumerationDescriptionMarshallingThrowsExceptionForInvalidValuesAndTypes() throws SIMPLDescriptionException, SIMPLTranslationException - { - EnumerationDescriptor ed = EnumerationDescriptor.get(primaryScenarioEnum.class); - ed.marshal("LOL A STRING"); // Strings are not enums, silly! - ed.marshal(secondaryScenarioEnum.secondValue); // That's not the right enum to marshal, silly! - ed.marshal(null); // Woah! Null?! I don't THINK so. - } - - @Test - public void enumerationDescriptionUnmarshallsValuesForCustomValuedEnums() throws SIMPLDescriptionException, SIMPLTranslationException - { - EnumerationDescriptor ed = EnumerationDescriptor.get(secondaryScenarioEnum.class); - assertEquals(secondaryScenarioEnum.firstValue, ed.unmarshal("firstValue")); - assertEquals(secondaryScenarioEnum.firstValue, ed.unmarshal("3")); - - assertEquals(secondaryScenarioEnum.thirdValue, ed.unmarshal("thirdValue")); - assertEquals(secondaryScenarioEnum.thirdValue, ed.unmarshal("7")); - } - - @Test(expected=SIMPLTranslationException.class) - public void enumerationDescriptionThrowsExceptionOnUnmarshallingNonExistantNames() throws SIMPLDescriptionException, SIMPLTranslationException - { - EnumerationDescriptor ed = EnumerationDescriptor.get(secondaryScenarioEnum.class); - ed.unmarshal(null);// Null? NOPE. - ed.unmarshal(""); // Empty? NOPE. - ed.unmarshal("thisIsSomeValueThatIsNotInTheEnumerationAtAll"); // Not gonna happen. - } - - @Test(expected=SIMPLTranslationException.class) - public void enumerationDescriptionThrowsExceptionOnUnmarshallingNonExistantValues() throws SIMPLDescriptionException, SIMPLTranslationException - { - EnumerationDescriptor ed = EnumerationDescriptor.get(secondaryScenarioEnum.class); - ed.unmarshal("-1"); // Not in there. - ed.unmarshal("90001"); // also not in there. - } -} - +package ecologylab.serialization; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class EnumerationDescriptionTest { + + @Test(expected=SIMPLDescriptionException.class) + public void descriptionsForNonEnumTypesProvokeException() throws SIMPLDescriptionException + { + EnumerationDescriptor invalid = EnumerationDescriptor.get(ClassDescriptor.class); + } + + @Test + public void descriptionForBasicEnumerationsWorks() throws SIMPLDescriptionException { + EnumerationDescriptor ed = EnumerationDescriptor.get(primaryScenarioEnum.class); + + assertTrue("There is no information about this enum", ed.metaInfo.isEmpty()); + assertTrue("There are no other tags for this enum", ed.otherTags.isEmpty()); + + assertEquals("The packageName must be correct" , primaryScenarioEnum.class.getPackage().getName(), ed.getPackageName()); + assertEquals("The javaName must be correct", primaryScenarioEnum.class.getName(), ed.getJavaTypeName()); + assertEquals("The Simpl name must be correct", "primaryScenarioEnum", ed.getName()); + + assertEquals("There should be three entries for this enum", 3, ed.getEnumerationEntries().size()); + + assertTrue("Should contain all of the values of the enum! Missing first", ed.containsEntry("firstValue")); + assertTrue("Should contain all of the values of the enum! Missing second", ed.containsEntry("secondValue")); + assertTrue("Should contain all of the values of the enum! Missing third", ed.containsEntry("thirdValue")); + assertFalse("Should not contain a value that isn't in the enum! There are no Jibbles here!", ed.containsEntry("jibbles")); + assertFalse("Should be case sensitive! FIRSTENTRY ignores casing.", ed.containsEntry("FIRSTENTRY")); + + assertEquals("Should fetch the correct enumeration value; expected firstValue", primaryScenarioEnum.firstValue, ed.getEntryEnumValue("firstValue")); + assertEquals("Should fetch the correct enumeration value; expected secondValue", primaryScenarioEnum.secondValue, ed.getEntryEnumValue("secondValue")); + assertEquals("Should fetch the correct enumeration value; expected thirdValue", primaryScenarioEnum.thirdValue, ed.getEntryEnumValue("thirdValue")); + } + + /** + * This handles some of the validations that should apply for most of the test cases; + * these have been copy pasted from the prior test case so they can be reused... + * I could have refactored this in the first test case to a method call, but I felt it was nicer w/ the core assumptions there. + * @param ed + */ + private void performBasicValidations(Class enumClass, EnumerationDescriptor ed) + { + assertTrue("There is no information about this enum", ed.metaInfo.isEmpty()); + assertTrue("There are no other tags for this enum", ed.otherTags.isEmpty()); + + assertEquals("The packageName must be correct" , enumClass.getPackage().getName(), ed.getPackageName()); + assertEquals("The javaName must be correct", enumClass.getName(), ed.getJavaTypeName()); + assertEquals("The Simpl name must be correct", enumClass.getSimpleName(), ed.getName()); + + assertEquals("There should be three entries for this enum", 3, ed.getEnumerationEntries().size()); + + assertTrue("Should contain all of the values of the enum! Missing first", ed.containsEntry("firstValue")); + assertTrue("Should contain all of the values of the enum! Missing second", ed.containsEntry("secondValue")); + assertTrue("Should contain all of the values of the enum! Missing third", ed.containsEntry("thirdValue")); + assertFalse("Should not contain a value that isn't in the enum! There are no Jibbles here!", ed.containsEntry("jibbles")); + assertFalse("Should be case sensitive! FIRSTENTRY ignores casing.", ed.containsEntry("FIRSTENTRY")); + } + + @Test(expected=SIMPLDescriptionException.class) + public void descriptionForCustomValuedEnumerationsWithoutASimplFieldProvokesException() throws SIMPLDescriptionException + { + EnumerationDescriptor invalid = EnumerationDescriptor.get(invalidEnumExample.class); + } + + @Test(expected=SIMPLDescriptionException.class) + public void descriptionForCustomValuedEnumerationsWithInvalidSimplFieldTypesProvokesException() throws SIMPLDescriptionException + { + EnumerationDescriptor invalid = EnumerationDescriptor.get(secondaryScenarioRejectsNonIntegers.class); + } + + @Test + public void customValuedEnumerartionsAreCorrectlyIdentified() + { + // Valid "custom valued" enumerations should, of course, be identified as such + assertTrue(EnumerationDescriptor.isCustomValuedEnum(secondaryScenarioEnum.class)); + assertTrue(EnumerationDescriptor.isCustomValuedEnum(secondaryScenarioAlsoSupportsPrimitiveIntEnum.class)); + + // Invalid "custom valued" enumerations (due to typing issues / lack of simpl_scalar) should be identified as "custom valued" + // so that other description code can through the appropriate exceptions + assertTrue(EnumerationDescriptor.isCustomValuedEnum(secondaryScenarioRejectsNonIntegers.class)); + + // Standard enumerations (like the basic scenario) should NOT be considered custom valued... + // Because, duh, they're not. + assertFalse("This enumeration has no custom values.", EnumerationDescriptor.isCustomValuedEnum(primaryScenarioEnum.class)); + + + // Things that are not enums are also, very obviously, not Custom Valued enumerations + assertFalse(EnumerationDescriptor.isCustomValuedEnum(String.class)); + } + + @Test + public void descriptionForCustomValuedEnumerationsWorks() throws SIMPLDescriptionException { + + EnumerationDescriptor ed = EnumerationDescriptor.get(secondaryScenarioEnum.class); + performBasicValidations(secondaryScenarioEnum.class, ed); + + // let's get the core first, then do some value marshalling. ;P + assertEquals(new Integer(3), ed.getEntryEnumIntegerValue("firstValue")); + assertEquals(new Integer(5), ed.getEntryEnumIntegerValue("secondValue")); + assertEquals(new Integer(7), ed.getEntryEnumIntegerValue("thirdValue")); + + EnumerationDescriptor secondStyle = EnumerationDescriptor.get(secondaryScenarioAlsoSupportsPrimitiveIntEnum.class); + performBasicValidations(secondaryScenarioAlsoSupportsPrimitiveIntEnum.class, secondStyle); + performValueValidation(secondStyle); + } + + private void performValueValidation(EnumerationDescriptor ed) + { + assertEquals(new Integer(3), ed.getEntryEnumIntegerValue("firstValue")); + assertEquals(new Integer(5), ed.getEntryEnumIntegerValue("secondValue")); + assertEquals(new Integer(7), ed.getEntryEnumIntegerValue("thirdValue")); + + assertEquals("firstValue", ed.getEntryEnumFromValue(3).toString()); + assertEquals("secondValue", ed.getEntryEnumFromValue(5).toString()); + assertEquals("thirdValue", ed.getEntryEnumFromValue(7).toString()); + + } + + @Test + public void enumerationDescriptionMarshalsValuesCorrectlyForNormalEnums() throws SIMPLDescriptionException, SIMPLTranslationException + { + // This is like, the simplest case. If this goes wrong, tears and shame should be part of the fix. + EnumerationDescriptor ed = EnumerationDescriptor.get(primaryScenarioEnum.class); + assertEquals("firstValue", ed.marshal(primaryScenarioEnum.firstValue)); + assertEquals("secondValue", ed.marshal(primaryScenarioEnum.secondValue)); + } + + @Test + public void enumerationDescriptionMarshalsValuesForCustomValuedEnums() throws SIMPLTranslationException, SIMPLDescriptionException + { + // This is like, the simplest case. If this goes wrong, tears and shame should be part of the fix. + EnumerationDescriptor ed = EnumerationDescriptor.get(secondaryScenarioEnum.class); + assertEquals("firstValue", ed.marshal(secondaryScenarioEnum.firstValue)); + assertEquals("secondValue", ed.marshal(secondaryScenarioEnum.secondValue)); + // Yes. This test was basically copy pasted. + } + + + @Test(expected=SIMPLTranslationException.class) + public void enumerationDescriptionMarshallingThrowsExceptionForInvalidValuesAndTypes() throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptor ed = EnumerationDescriptor.get(primaryScenarioEnum.class); + ed.marshal("LOL A STRING"); // Strings are not enums, silly! + ed.marshal(secondaryScenarioEnum.secondValue); // That's not the right enum to marshal, silly! + ed.marshal(null); // Woah! Null?! I don't THINK so. + } + + @Test + public void enumerationDescriptionUnmarshallsValuesForCustomValuedEnums() throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptor ed = EnumerationDescriptor.get(secondaryScenarioEnum.class); + assertEquals(secondaryScenarioEnum.firstValue, ed.unmarshal("firstValue")); + assertEquals(secondaryScenarioEnum.firstValue, ed.unmarshal("3")); + + assertEquals(secondaryScenarioEnum.thirdValue, ed.unmarshal("thirdValue")); + assertEquals(secondaryScenarioEnum.thirdValue, ed.unmarshal("7")); + } + + @Test(expected=SIMPLTranslationException.class) + public void enumerationDescriptionThrowsExceptionOnUnmarshallingNonExistantNames() throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptor ed = EnumerationDescriptor.get(secondaryScenarioEnum.class); + ed.unmarshal(null);// Null? NOPE. + ed.unmarshal(""); // Empty? NOPE. + ed.unmarshal("thisIsSomeValueThatIsNotInTheEnumerationAtAll"); // Not gonna happen. + } + + @Test(expected=SIMPLTranslationException.class) + public void enumerationDescriptionThrowsExceptionOnUnmarshallingNonExistantValues() throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptor ed = EnumerationDescriptor.get(secondaryScenarioEnum.class); + ed.unmarshal("-1"); // Not in there. + ed.unmarshal("90001"); // also not in there. + } +} + diff --git a/simplCore/test/ecologylab/serialization/enumIssueTestClass.java b/simplCore/test/ecologylab/serialization/enumIssueTestClass.java index f5ca6367..0e6dc5d6 100644 --- a/simplCore/test/ecologylab/serialization/enumIssueTestClass.java +++ b/simplCore/test/ecologylab/serialization/enumIssueTestClass.java @@ -1,19 +1,19 @@ -package ecologylab.serialization; - -import java.util.ArrayList; - -import ecologylab.serialization.annotations.FieldUsage; -import ecologylab.serialization.annotations.simpl_collection; - -public class enumIssueTestClass { - - @simpl_collection - private ArrayList ourUsages; - - @simpl_collection - private ArrayList notGeneric; - - @simpl_collection - private ArrayList composite; - -} +package ecologylab.serialization; + +import java.util.ArrayList; + +import ecologylab.serialization.annotations.FieldUsage; +import ecologylab.serialization.annotations.simpl_collection; + +public class enumIssueTestClass { + + @simpl_collection + private ArrayList ourUsages; + + @simpl_collection + private ArrayList notGeneric; + + @simpl_collection + private ArrayList composite; + +} diff --git a/simplCore/test/ecologylab/serialization/invalidEnumExample.java b/simplCore/test/ecologylab/serialization/invalidEnumExample.java index 9abeb84d..6ef086bd 100644 --- a/simplCore/test/ecologylab/serialization/invalidEnumExample.java +++ b/simplCore/test/ecologylab/serialization/invalidEnumExample.java @@ -1,16 +1,16 @@ -package ecologylab.serialization; - - -public enum invalidEnumExample { - - firstValue(3), - secondValue(5), - thirdValue(7); - - private Integer myValue; - - private invalidEnumExample(Integer aValue) - { - this.myValue = aValue; - } -} +package ecologylab.serialization; + + +public enum invalidEnumExample { + + firstValue(3), + secondValue(5), + thirdValue(7); + + private Integer myValue; + + private invalidEnumExample(Integer aValue) + { + this.myValue = aValue; + } +} diff --git a/simplCore/test/ecologylab/serialization/primaryScenarioEnum.java b/simplCore/test/ecologylab/serialization/primaryScenarioEnum.java index 8f11ba86..c3a7ad85 100644 --- a/simplCore/test/ecologylab/serialization/primaryScenarioEnum.java +++ b/simplCore/test/ecologylab/serialization/primaryScenarioEnum.java @@ -1,13 +1,13 @@ -package ecologylab.serialization; - -/** - * A enumeration that demonstrates the primary scenario for enumerated types: - * A type with names and compiler-assigned values - * @author tom - * - */ -public enum primaryScenarioEnum { - firstValue, - secondValue, - thirdValue -} +package ecologylab.serialization; + +/** + * A enumeration that demonstrates the primary scenario for enumerated types: + * A type with names and compiler-assigned values + * @author tom + * + */ +public enum primaryScenarioEnum { + firstValue, + secondValue, + thirdValue +} diff --git a/simplCore/test/ecologylab/serialization/secondaryScenarioAlsoSupportsPrimitiveIntEnum.java b/simplCore/test/ecologylab/serialization/secondaryScenarioAlsoSupportsPrimitiveIntEnum.java index ceaf7c8b..50ddb870 100644 --- a/simplCore/test/ecologylab/serialization/secondaryScenarioAlsoSupportsPrimitiveIntEnum.java +++ b/simplCore/test/ecologylab/serialization/secondaryScenarioAlsoSupportsPrimitiveIntEnum.java @@ -1,18 +1,18 @@ -package ecologylab.serialization; - -import ecologylab.serialization.annotations.simpl_scalar; - -public enum secondaryScenarioAlsoSupportsPrimitiveIntEnum { - - firstValue(3), - secondValue(5), - thirdValue(7); - - @simpl_scalar - private int myValue; - - private secondaryScenarioAlsoSupportsPrimitiveIntEnum(int aValue) - { - this.myValue = aValue; - } +package ecologylab.serialization; + +import ecologylab.serialization.annotations.simpl_scalar; + +public enum secondaryScenarioAlsoSupportsPrimitiveIntEnum { + + firstValue(3), + secondValue(5), + thirdValue(7); + + @simpl_scalar + private int myValue; + + private secondaryScenarioAlsoSupportsPrimitiveIntEnum(int aValue) + { + this.myValue = aValue; + } } \ No newline at end of file diff --git a/simplCore/test/ecologylab/serialization/secondaryScenarioEnum.java b/simplCore/test/ecologylab/serialization/secondaryScenarioEnum.java index e61cdd88..050b5a03 100644 --- a/simplCore/test/ecologylab/serialization/secondaryScenarioEnum.java +++ b/simplCore/test/ecologylab/serialization/secondaryScenarioEnum.java @@ -1,18 +1,18 @@ -package ecologylab.serialization; - -import ecologylab.serialization.annotations.simpl_scalar; - -public enum secondaryScenarioEnum { - - firstValue(3), - secondValue(5), - thirdValue(7); - - @simpl_scalar - private Integer myValue; - - private secondaryScenarioEnum(Integer aValue) - { - this.myValue = aValue; - } +package ecologylab.serialization; + +import ecologylab.serialization.annotations.simpl_scalar; + +public enum secondaryScenarioEnum { + + firstValue(3), + secondValue(5), + thirdValue(7); + + @simpl_scalar + private Integer myValue; + + private secondaryScenarioEnum(Integer aValue) + { + this.myValue = aValue; + } } \ No newline at end of file diff --git a/simplCore/test/ecologylab/serialization/secondaryScenarioRejectsNonIntegers.java b/simplCore/test/ecologylab/serialization/secondaryScenarioRejectsNonIntegers.java index 7af6d602..bf83e64c 100644 --- a/simplCore/test/ecologylab/serialization/secondaryScenarioRejectsNonIntegers.java +++ b/simplCore/test/ecologylab/serialization/secondaryScenarioRejectsNonIntegers.java @@ -1,18 +1,18 @@ -package ecologylab.serialization; - -import ecologylab.serialization.annotations.simpl_scalar; - -public enum secondaryScenarioRejectsNonIntegers { - - firstValue("3"), - secondValue("5"), - thirdValue("7"); - - @simpl_scalar - private String myValue; - - private secondaryScenarioRejectsNonIntegers(String aValue) - { - this.myValue = aValue; - } +package ecologylab.serialization; + +import ecologylab.serialization.annotations.simpl_scalar; + +public enum secondaryScenarioRejectsNonIntegers { + + firstValue("3"), + secondValue("5"), + thirdValue("7"); + + @simpl_scalar + private String myValue; + + private secondaryScenarioRejectsNonIntegers(String aValue) + { + this.myValue = aValue; + } } \ No newline at end of file diff --git a/simplCore/test/ecologylab/serialization/simplstringformats/JSONFormatTest.java b/simplCore/test/ecologylab/serialization/simplstringformats/JSONFormatTest.java index f8855af8..dd783645 100644 --- a/simplCore/test/ecologylab/serialization/simplstringformats/JSONFormatTest.java +++ b/simplCore/test/ecologylab/serialization/simplstringformats/JSONFormatTest.java @@ -1,19 +1,19 @@ -package ecologylab.serialization.simplstringformats; - -import static ecologylab.serialization.simplstringformats.SimplStringFormatTesting.roundtrip; - -import org.junit.Test; - -import ecologylab.serialization.ISimplStringFormat; - - -public class JSONFormatTest { - - @Test - public void testAFewCases() { - ISimplStringFormat format = new JSONFormat(); - roundtrip(format, "the most basic string ever"); - roundtrip(format, "sad;lkfjsadf \r\n "); - } - -} +package ecologylab.serialization.simplstringformats; + +import static ecologylab.serialization.simplstringformats.SimplStringFormatTesting.roundtrip; + +import org.junit.Test; + +import ecologylab.serialization.ISimplStringFormat; + + +public class JSONFormatTest { + + @Test + public void testAFewCases() { + ISimplStringFormat format = new JSONFormat(); + roundtrip(format, "the most basic string ever"); + roundtrip(format, "sad;lkfjsadf \r\n "); + } + +} diff --git a/simplCore/test/ecologylab/serialization/simplstringformats/SimplStringFormatTesting.java b/simplCore/test/ecologylab/serialization/simplstringformats/SimplStringFormatTesting.java index e970d1c7..12e78708 100644 --- a/simplCore/test/ecologylab/serialization/simplstringformats/SimplStringFormatTesting.java +++ b/simplCore/test/ecologylab/serialization/simplstringformats/SimplStringFormatTesting.java @@ -1,15 +1,15 @@ -package ecologylab.serialization.simplstringformats; - -import org.junit.Assert; - -import ecologylab.serialization.ISimplStringFormat; - -public class SimplStringFormatTesting { - - public static void roundtrip(ISimplStringFormat format, String toTest) - { - String escaped = format.escape(toTest); - String unescaped = format.unescape(escaped); - Assert.assertEquals("Roundtrip failed on format: " + format.getClass().getName() , toTest, unescaped); - } -} +package ecologylab.serialization.simplstringformats; + +import org.junit.Assert; + +import ecologylab.serialization.ISimplStringFormat; + +public class SimplStringFormatTesting { + + public static void roundtrip(ISimplStringFormat format, String toTest) + { + String escaped = format.escape(toTest); + String unescaped = format.unescape(escaped); + Assert.assertEquals("Roundtrip failed on format: " + format.getClass().getName() , toTest, unescaped); + } +} diff --git a/simplCore/test/ecologylab/serialization/simplstringformats/XMLFormatTest.java b/simplCore/test/ecologylab/serialization/simplstringformats/XMLFormatTest.java index fcbecdc7..a0ff002e 100644 --- a/simplCore/test/ecologylab/serialization/simplstringformats/XMLFormatTest.java +++ b/simplCore/test/ecologylab/serialization/simplstringformats/XMLFormatTest.java @@ -1,17 +1,17 @@ -package ecologylab.serialization.simplstringformats; - -import static ecologylab.serialization.simplstringformats.SimplStringFormatTesting.roundtrip; - -import org.junit.Test; - -import ecologylab.serialization.ISimplStringFormat; - -public class XMLFormatTest { - - @Test - public void testAFewCases() { - ISimplStringFormat format = new XMLFormat(); - roundtrip(format, "sad;lkfjsadf \r\n "); - } - -} +package ecologylab.serialization.simplstringformats; + +import static ecologylab.serialization.simplstringformats.SimplStringFormatTesting.roundtrip; + +import org.junit.Test; + +import ecologylab.serialization.ISimplStringFormat; + +public class XMLFormatTest { + + @Test + public void testAFewCases() { + ISimplStringFormat format = new XMLFormat(); + roundtrip(format, "sad;lkfjsadf \r\n "); + } + +} diff --git a/simplPlatformSpecifics/Android/.gitignore b/simplPlatformSpecifics/Android/.gitignore deleted file mode 100644 index 14b2c45a..00000000 --- a/simplPlatformSpecifics/Android/.gitignore +++ /dev/null @@ -1,18 +0,0 @@ -#java specific -*.class - -#netbeans ignore personal stuff -nbproject/private/ - -#android specific -bin/ -gen/ - -## generic files to ignore -*~ -*.lock -*.DS_Store -*.swp -*.out - -bin/ecologylabfundamentalandroid.jar diff --git a/simplPlatformSpecifics/Android/bin/res/drawable-hdpi/icon.png b/simplPlatformSpecifics/Android/bin/res/drawable-hdpi/icon.png deleted file mode 100644 index 882eb148..00000000 Binary files a/simplPlatformSpecifics/Android/bin/res/drawable-hdpi/icon.png and /dev/null differ diff --git a/simplPlatformSpecifics/Android/bin/res/drawable-ldpi/icon.png b/simplPlatformSpecifics/Android/bin/res/drawable-ldpi/icon.png deleted file mode 100644 index 18689f65..00000000 Binary files a/simplPlatformSpecifics/Android/bin/res/drawable-ldpi/icon.png and /dev/null differ diff --git a/simplPlatformSpecifics/Android/bin/res/drawable-mdpi/icon.png b/simplPlatformSpecifics/Android/bin/res/drawable-mdpi/icon.png deleted file mode 100644 index 02e96b96..00000000 Binary files a/simplPlatformSpecifics/Android/bin/res/drawable-mdpi/icon.png and /dev/null differ diff --git a/simplPlatformSpecifics/Sun/.gitignore b/simplPlatformSpecifics/Sun/.gitignore deleted file mode 100644 index 1750f48f..00000000 --- a/simplPlatformSpecifics/Sun/.gitignore +++ /dev/null @@ -1,18 +0,0 @@ -#java specific -*.class - -#netbeans ignore personal stuff -nbproject/private/ - - -## generic files to ignore -*~ -*.lock -*.DS_Store -*.swp -*.out - -.settings/ -bin -src/META-INF/ - diff --git a/simplPlatformSpecifics/Sun/.classpath b/simplSunSpecifics/.classpath similarity index 76% rename from simplPlatformSpecifics/Sun/.classpath rename to simplSunSpecifics/.classpath index d9967f52..5280c5d8 100644 --- a/simplPlatformSpecifics/Sun/.classpath +++ b/simplSunSpecifics/.classpath @@ -1,7 +1,8 @@ - - - - - - - + + + + + + + + diff --git a/simplPlatformSpecifics/Sun/.project b/simplSunSpecifics/.project similarity index 95% rename from simplPlatformSpecifics/Sun/.project rename to simplSunSpecifics/.project index 69a58b81..02fd8b98 100644 --- a/simplPlatformSpecifics/Sun/.project +++ b/simplSunSpecifics/.project @@ -1,17 +1,17 @@ - - - simplSunSpecifics - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - + + + simplSunSpecifics + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/simplSunSpecifics/build.xml b/simplSunSpecifics/build.xml new file mode 100644 index 00000000..f0a82967 --- /dev/null +++ b/simplSunSpecifics/build.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/MetaPrefColor.java b/simplSunSpecifics/src/ecologylab/appframework/types/prefs/MetaPrefColor.java similarity index 95% rename from simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/MetaPrefColor.java rename to simplSunSpecifics/src/ecologylab/appframework/types/prefs/MetaPrefColor.java index 244e6de4..a11a139c 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/MetaPrefColor.java +++ b/simplSunSpecifics/src/ecologylab/appframework/types/prefs/MetaPrefColor.java @@ -1,71 +1,71 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import java.awt.Color; - -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.TypeRegistry; - -/** - * @author awebb - * - */ -public class MetaPrefColor extends MetaPref -{ - /** - * Default value for this MetaPref - */ - @simpl_scalar Color defaultValue; - - public static final ScalarType COLOR_SCALAR_TYPE = TypeRegistry.getScalarType(Color.class); - - public MetaPrefColor() - { - super(COLOR_SCALAR_TYPE); - } - - /** - * Gets the default value of a MetaPref. - * - * @return Default value of MetaPref, or Black if null. - */ - @Override - public Color getDefaultValue() - { - return (defaultValue != null) ? defaultValue : Color.BLACK; - } - - /** - * Construct a new instance of the Pref that matches this. - * Use this to fill-in the default value. - * - * @return new Pref instance - */ - @Override - protected Pref getPrefInstance() - { - return new PrefColor(); - } - - /** - * Get max value; returns null for this type. - */ - @Override - public Color getMaxValue() - { - return null; - } - - /** - * Get min value; returns null for this type. - */ - @Override - public Color getMinValue() - { - return null; - } - -} +/** + * + */ +package ecologylab.appframework.types.prefs; + +import java.awt.Color; + +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.TypeRegistry; + +/** + * @author awebb + * + */ +public class MetaPrefColor extends MetaPref +{ + /** + * Default value for this MetaPref + */ + @simpl_scalar Color defaultValue; + + public static final ScalarType COLOR_SCALAR_TYPE = TypeRegistry.getScalarType(Color.class); + + public MetaPrefColor() + { + super(COLOR_SCALAR_TYPE); + } + + /** + * Gets the default value of a MetaPref. + * + * @return Default value of MetaPref, or Black if null. + */ + @Override + public Color getDefaultValue() + { + return (defaultValue != null) ? defaultValue : Color.BLACK; + } + + /** + * Construct a new instance of the Pref that matches this. + * Use this to fill-in the default value. + * + * @return new Pref instance + */ + @Override + protected Pref getPrefInstance() + { + return new PrefColor(); + } + + /** + * Get max value; returns null for this type. + */ + @Override + public Color getMaxValue() + { + return null; + } + + /** + * Get min value; returns null for this type. + */ + @Override + public Color getMinValue() + { + return null; + } + +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/PrefColor.java b/simplSunSpecifics/src/ecologylab/appframework/types/prefs/PrefColor.java similarity index 93% rename from simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/PrefColor.java rename to simplSunSpecifics/src/ecologylab/appframework/types/prefs/PrefColor.java index df9656fa..b9abe13b 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/PrefColor.java +++ b/simplSunSpecifics/src/ecologylab/appframework/types/prefs/PrefColor.java @@ -1,71 +1,71 @@ -/** - * - */ -package ecologylab.appframework.types.prefs; - -import java.awt.Color; - -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * A preference that is a Color. - * - * @author awebb - * - */ -public class PrefColor extends Pref -{ - @simpl_scalar - Color value; - - public PrefColor() - { - super(); - } - - public PrefColor(Color value) - { - super(); - this.value = value; - } - - public PrefColor(String name, Color value) - { - super(); - this.name = name; - this.value = value; - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#getValue() - */ - @Override - protected Color getValue() - { - return value; - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#setValue(T) - */ - @Override - public void setValue(Color newValue) - { - this.value = newValue; - - prefChanged(); - } - - /** - * @see ecologylab.appframework.types.prefs.Pref#clone() - */ - @Override - public Pref clone() - { - return new PrefColor(this.name, this.value); - } - - public void register(){ - super.register(); - } +/** + * + */ +package ecologylab.appframework.types.prefs; + +import java.awt.Color; + +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * A preference that is a Color. + * + * @author awebb + * + */ +public class PrefColor extends Pref +{ + @simpl_scalar + Color value; + + public PrefColor() + { + super(); + } + + public PrefColor(Color value) + { + super(); + this.value = value; + } + + public PrefColor(String name, Color value) + { + super(); + this.name = name; + this.value = value; + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#getValue() + */ + @Override + protected Color getValue() + { + return value; + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#setValue(T) + */ + @Override + public void setValue(Color newValue) + { + this.value = newValue; + + prefChanged(); + } + + /** + * @see ecologylab.appframework.types.prefs.Pref#clone() + */ + @Override + public Pref clone() + { + return new PrefColor(this.name, this.value); + } + + public void register(){ + super.register(); + } } \ No newline at end of file diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/PrefDelayedOp.java b/simplSunSpecifics/src/ecologylab/appframework/types/prefs/PrefDelayedOp.java similarity index 100% rename from simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/PrefDelayedOp.java rename to simplSunSpecifics/src/ecologylab/appframework/types/prefs/PrefDelayedOp.java diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/gui/PrefEditorWidgets.java b/simplSunSpecifics/src/ecologylab/appframework/types/prefs/gui/PrefEditorWidgets.java similarity index 96% rename from simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/gui/PrefEditorWidgets.java rename to simplSunSpecifics/src/ecologylab/appframework/types/prefs/gui/PrefEditorWidgets.java index 282a904a..a2c3b17b 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/gui/PrefEditorWidgets.java +++ b/simplSunSpecifics/src/ecologylab/appframework/types/prefs/gui/PrefEditorWidgets.java @@ -1,723 +1,723 @@ -/** - * - */ -package ecologylab.appframework.types.prefs.gui; - -import java.awt.GridBagConstraints; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.LinkedHashMap; -import java.util.Map; - -import javax.swing.Action; -import javax.swing.JCheckBox; -import javax.swing.JColorChooser; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JSlider; -import javax.swing.JSpinner; -import javax.swing.JTextField; -import javax.swing.SpinnerNumberModel; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - -import ecologylab.appframework.types.prefs.Choice; -import ecologylab.appframework.types.prefs.MetaPref; -import ecologylab.appframework.types.prefs.MetaPrefBoolean; -import ecologylab.appframework.types.prefs.MetaPrefFloat; -import ecologylab.appframework.types.prefs.MetaPrefInt; -import ecologylab.appframework.types.prefs.MetaPrefSet; -import ecologylab.appframework.types.prefs.Pref; -import ecologylab.appframework.types.prefs.PrefSet; -import ecologylab.appframework.types.prefs.ValueChangedListener; -import ecologylab.collections.Scope; -import ecologylab.generic.Debug; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.Format; - -/** - * Contains methods for creating widgets associated with Prefs. - * - * @author Zachary O. Toups (toupsz@cs.tamu.edu) - */ -public class PrefEditorWidgets extends Debug implements ChangeListener -{ - /** - * The string that will be added to the metapref's id, to create a unique identifier for a - * jComponent. - */ - static final String IDENTIFIER_CHECK_BOX = "checkBox"; - - /** - * The string that will be added to the metapref's id, to create a unique identifier for a - * jComponent. - */ - static final String IDENTIFIER_BOOLEAN_NO = "No"; - - /** - * The string that will be added to the metapref's id, to create a unique identifier for a - * jComponent. - */ - static final String IDENTIFIER_BOOLEAN_YES = "Yes"; - - /** - * The string that will be added to the metapref's id, to create a unique identifier for a - * jComponent. - */ - static final String IDENTIFIER_FILE_CHOOSER = "fileChooser"; - - /** - * The string that will be added to the metapref's id, to create a unique identifier for a - * jComponent. - */ - static final String IDENTIFIER_COLOR_CHOOSER = "colorChooser"; - - /** - * The string that will be added to the metapref's id, to create a unique identifier for a - * jComponent. - */ - public static final String IDENTIFIER_SPINNER = "spinner"; - - /** - * The string that will be added to the metapref's id, to create a unique identifier for a - * jComponent. - */ - static final String IDENTIFIER_SLIDER = "slider"; - - /** - * The string that will be added to the metapref's id, to create a unique identifier for a - * jComponent. - */ - static final String IDENTIFIER_DROPDOWN = "dropdown"; - - /** - * The string that will be added to the metapref's id, to create a unique identifier for a - * jComponent. - */ - static final String IDENTIFIER_TEXT_FIELD = "textField"; - - /** - * The amount by which floats should be multiplied for use with sliders. If this number is 10, you - * will be able to see the 1 digit after the decimal when the number is changed back (10.1). For - * 100, you will have 2 digits after the decimal (10.11). Etc. - */ - static final int FLOAT_SLIDER_MODIFIER = 10; - - /** - * The inset between the right side of the gui panel and the right side of values. - */ - protected static final int RIGHT_GUI_INSET = 20; - - /** - * The padding between the default value in a text field and either side of the text field. - */ - protected static final int TEXT_FIELD_PADDING = 50; - - /** - * Okay, this is really, really important. The map goes like this: CategoryName to (MetaPrefName - * to (Array of JComponents)) So for each category, you get a sorted map of the metaprefs in that - * category. From that map you can get a list of all the components for a metapref by name. - */ - protected HashMap>> jCatComponentsMap = new HashMap>>(); - - /** Set of MetaPrefs */ - protected MetaPrefSet metaPrefSet; - - /** Set of Prefs */ - protected PrefSet prefSet; - - /** PURL to save prefs.xml to */ - protected ParsedURL savePrefsPURL; - - /** - * Content pane within base window for GUI - */ - protected JPanel jContentPane; - - /** - * The base function that you call to construct the prefs editor GUI. This requires that the - * MetaPrefSet and PrefSet be instantiated and populated prior to call. This function creates the - * entire GUI and handles all actions for it. - * - * @param metaPrefSet - * Set of MetaPrefs - * @param prefSet - * Set of Prefs - * @param savePrefsPURL - * ParsedURL to save prefs.xml to - * @param isStandalone - * Whether or not we're calling this standalone - */ - public PrefEditorWidgets(MetaPrefSet metaPrefSet, PrefSet prefSet, ParsedURL savePrefsPURL) - { - this.metaPrefSet = metaPrefSet; - this.prefSet = prefSet; - this.savePrefsPURL = savePrefsPURL; - } - - /** - * Creates a text field. - * - * @param panel - * JPanel this field will be associated with. - * @param mp - * MetaPref this field is for. - * - * @return JTextField with properties initialized to parameters. - */ - protected JTextField createTextField(JPanel panel, MetaPref mp) - { - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.FIRST_LINE_START; - - JTextField textField = new JTextField(); - textField.setHorizontalAlignment(JTextField.CENTER); - textField.setText(mp.getDefaultValue().toString()); - textField.setName(IDENTIFIER_TEXT_FIELD); - c.gridx = 0; - c.gridy = 0; - c.insets = new Insets(0, 0, 0, RIGHT_GUI_INSET); // top,left,bottom,right - c.ipadx = TEXT_FIELD_PADDING; - - panel.add(textField, c); - - // add metapref's component to array - Scope mpComponents = jCatComponentsMap.get(mp.getCategory()).get(mp.getID()); - if (mpComponents != null) - { - registerComponent(mp, IDENTIFIER_TEXT_FIELD, textField); - } - - return textField; - } - - /** - * Creates a check box. - * - * @param panel - * JPanel this button will be associated with. - * @param mp - * MetaPref this checkbox is being created for. - * - * @return JCheckBox with properties initialized to parameters. - */ - protected JCheckBox createCheckBox(JPanel panel, MetaPref mp) - { - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.LINE_START; - - JCheckBox checkBox = new JCheckBox(); - - checkBox.setSelected((Boolean) mp.getDefaultValue()); - checkBox.setName(IDENTIFIER_CHECK_BOX); - c.gridx = 0; - c.gridy = 0; - c.insets = new Insets(0, 0, 0, RIGHT_GUI_INSET); // top,left,bottom,right - - panel.add(checkBox, c); - - // add metapref's component to array - Scope mpComponents = jCatComponentsMap.get(mp.getCategory()).get(mp.getID()); - if (mpComponents != null) - { - registerComponent(mp, IDENTIFIER_CHECK_BOX, checkBox); - } - - return checkBox; - } - - /** - * Creates a drop down menu; combo box. - * - * @param panel - * JPanel this field will be associated with. - * @param mp - * MetaPref this combo box is being created for. - * - * @return JComboBox with properties initialized to parameters. - */ - protected JComboBox createDropDown(JPanel panel, MetaPref mp) - { - ArrayList> choices = mp.getChoices(); - T defValue = mp.getDefaultValue(); - if (choices != null) - { - String[] choiceLabels = new String[choices.size()]; - int i = 0; - int selected = 0; - for (Choice choice : choices) - { - choiceLabels[i] = choice.getLabel(); - if (choice.getValue() == defValue) - selected = i; - i++; - } - - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.FIRST_LINE_START; - - JComboBox comboBox = new JComboBox(choiceLabels); - comboBox.setSelectedIndex(selected); - comboBox.setName(IDENTIFIER_DROPDOWN); - c.gridx = 0; - c.gridy = 0; - c.insets = new Insets(0, 0, 0, RIGHT_GUI_INSET); // top,left,bottom,right - c.ipadx = TEXT_FIELD_PADDING; - - panel.add(comboBox, c); - - // add metapref's component to array - Scope mpComponents = jCatComponentsMap.get(mp.getCategory()).get(mp.getID()); - if (mpComponents != null) - { - registerComponent(mp, IDENTIFIER_DROPDOWN, comboBox); - } - - return comboBox; - } - return null; - } - - /** - * Creates a slider. - * - * @param panel - * JPanel this slider will be associated with. - * @param mp - * MetaPref this slider is being created for. - * @param labelAndName - * Name of slider - * @param valuesAreAltered - * Whether or not the values of the metapref/pref need to be altered for the slider. - * @param valueAlteredBy - * How much the metapref/pref values are multiplied/ divided by. Only used if - * valuesAreAltered=true. - * - * @return JSlider with properties initialized to parameters. - */ - protected JSlider createSlider(JPanel panel, MetaPref mp, String labelAndName, - boolean valuesAreAltered, int valueAlteredBy) - { - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.LINE_START; - - JSlider jSlider = new JSlider(); - if (valuesAreAltered) - { - // values must be altered by the modifier parameter - int newMin = (int) ((Float) mp.getMinValue() * FLOAT_SLIDER_MODIFIER); - int newMax = (int) ((Float) mp.getMaxValue() * FLOAT_SLIDER_MODIFIER); - int defVal = (int) ((Float) mp.getDefaultValue() * FLOAT_SLIDER_MODIFIER); - jSlider.setMinimum(newMin); - jSlider.setMaximum(newMax); - jSlider.setValue(defVal); - jSlider.setMajorTickSpacing(FLOAT_SLIDER_MODIFIER * 5); - jSlider.setMinorTickSpacing(FLOAT_SLIDER_MODIFIER / 5); - Float curValue = new Float((float) (jSlider.getValue()) / FLOAT_SLIDER_MODIFIER); - jSlider.setToolTipText(curValue.toString()); - - // we need to mess with the labels so they display the correct - // values. - Hashtable labelTable = jSlider.createStandardLabels( - FLOAT_SLIDER_MODIFIER * 5, newMin); - // add a label for the max value to the table if one doesn't exist - // already - if (!labelTable.containsKey(newMax)) - { - Hashtable maxLabelTable = jSlider.createStandardLabels( - FLOAT_SLIDER_MODIFIER * 5, newMax); - labelTable.putAll(maxLabelTable); - } - for (Map.Entry entry : labelTable.entrySet()) - { - // changes here ARE reflected in labelTable - - // NOTE: this is the way you would change/remove entries from - // list of labels. - // you cannot add entries here. see the Java API and: - // http://java.sun.com/docs/books/tutorial/uiswing/components/slider.html - // for more details - JLabel label = (JLabel) entry.getValue(); - Float value = new Float(label.getText()); - value = value / FLOAT_SLIDER_MODIFIER; - label.setText(value.toString()); - } - jSlider.setLabelTable(labelTable); - jSlider.setName(labelAndName + "thisisafloat"); - } - else - { - // default behavior - jSlider.setMinimum((Integer) mp.getMinValue()); - jSlider.setMaximum((Integer) mp.getMaxValue()); - jSlider.setValue((Integer) mp.getDefaultValue()); - jSlider.setMajorTickSpacing(10); - jSlider.setMinorTickSpacing(1); - Integer curValue = jSlider.getValue(); - jSlider.setToolTipText(curValue.toString()); - jSlider.setName(labelAndName); - } - - jSlider.setPaintTicks(true); - jSlider.setPaintLabels(true); - jSlider.addChangeListener(this); - c.gridx = 0; - c.gridy = 0; - c.insets = new Insets(0, 0, 0, RIGHT_GUI_INSET); // top,left,bottom,right - panel.add(jSlider, c); - - // add metapref's component to array - Scope mpComponents = jCatComponentsMap.get(mp.getCategory()).get(mp.getID()); - if (mpComponents != null) - { - registerComponent(mp, labelAndName, jSlider); - } - - return jSlider; - } - - /** - * Creates a spinner. This is a text field with up/down arrows that allow you to increase/decrease - * the value in the text box. - * - * @param panel - * JPanel this spinner will be associated with. - * @param mp - * MetaPref this spinner is being created for. - * - * @return JSpinner with properties initialized to parameters. - */ - protected JSpinner createSpinner(JPanel panel, MetaPref mp) - { - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.LINE_START; - - double stepSize = 1.0; - if (mp instanceof MetaPrefFloat) - stepSize = 0.1; - - SpinnerNumberModel numModel = new SpinnerNumberModel(); - numModel.setMinimum((Float) mp.getMinValue()); - numModel.setMaximum((Float) mp.getMaxValue()); - numModel.setValue(mp.getDefaultValue()); - numModel.setStepSize(stepSize); - - JSpinner jSpinner = new JSpinner(); - jSpinner.setModel(numModel); - jSpinner.setValue(mp.getDefaultValue()); - jSpinner.setName(IDENTIFIER_SPINNER); - c.gridx = 0; - c.gridy = 0; - c.insets = new Insets(0, 0, 0, RIGHT_GUI_INSET); // top,left,bottom,right - panel.add(jSpinner, c); - - // add metapref's component to array - Scope mpComponents = jCatComponentsMap.get(mp.getCategory()).get(mp.getID()); - if (mpComponents != null) - { - registerComponent(mp, IDENTIFIER_SPINNER, jSpinner); - } - - return jSpinner; - } - - /** - * Returns the ObjectRegistry for this MetaPref's jComponents. - * - * @param mp - * MetaPref whose jComponents we want. - * - * @return ObjectRegistry for MetaPref's jComponents. - */ - protected Scope jCatComponentsMap(MetaPref mp) - { - LinkedHashMap> categoryMap = this.jCatComponentsMap.get(mp - .getCategory()); - - if (categoryMap == null) - { - categoryMap = new LinkedHashMap>(); - this.jCatComponentsMap.put(mp.getCategory(), categoryMap); - } - - Scope result = categoryMap.get(mp.getID()); - if (result == null) - { - LinkedHashMap> catHash = jCatComponentsMap.get(mp.getCategory()); - result = new Scope(); - catHash.put(mp.getID(), result); - } - return result; - } - - /** - * Registers a JComponent with the ObjectRegistry - * - * @param mp - * metapref we want to register - * @param labelAndName - * label/name to add to the metapref's id to identify a particular jComponent. must be - * UNIQUE. - * @param jComponent - * jComponent to register - */ - public void registerComponent(MetaPref mp, String labelAndName, JComponent jComponent) - { - // println("Registering: " + this.id+labelAndName); - jCatComponentsMap(mp).put(mp.getID() + labelAndName, jComponent); - } - - /** - * This is for sliders; when we move the slider, we need to update the tooltip and force it to - * display. TODO: change placement of tooltip - */ - public void stateChanged(ChangeEvent e) - { - JSlider source = (JSlider) e.getSource(); - String name = source.getName(); - Float curVal = new Float(source.getValue()); - if (name.indexOf("thisisafloat") != -1) - { - curVal = curVal / FLOAT_SLIDER_MODIFIER; - source.setToolTipText(curVal.toString()); - } - else - { - source.setToolTipText(curVal.toString()); - } - Action action = source.getActionMap().get("postTip"); - if (action != null) - { - // show me the tooltip, NOW - action.actionPerformed(new ActionEvent(source, ActionEvent.ACTION_PERFORMED, "postTip")); - } - } - - /** - * Queries all widgets and updates their associated Prefs; this will cascade and cause each Pref - * to notify all PrefChangedListeners associated with Pref. - */ - public void updatePrefsFromWidgets() - { - /* - * we do this with metaprefs because we will always have all metaprefs. we may not always have a - * prefs file to start with. - */ - // this iterator organizes them by category - for (String cat : metaPrefSet.getCategories()) - { - for (MetaPref mp : metaPrefSet.getMetaPrefListByCategory(cat)) - { - Pref pref = mp.getAssociatedPref(); - Object editedValue = getPrefValue(mp); - if (editedValue == null) - { - Debug.error(this, "edited value = null for: " + mp.getID()); - } - else - { - Object previousValue = pref.value(); - pref.setValue(editedValue); - - // TODO probably take this code out; now setValue will notify - // all PrefChangedListeners that are registered with it. - ValueChangedListener valueChangedListener = mp.getValueChangedListener(); - if ((valueChangedListener != null) && (editedValue != null)) - { - if (!editedValue.equals(previousValue)) - valueChangedListener.valueChanged(pref); - } - - if (!prefSet.containsKey(pref.key())) - prefSet.add(pref); - } - } - } - } - - /** - * Get the pref value (if applicable) for a given metapref. - * - * @param mp - * metapref to fetch pref value for - * @return pref value or null - */ - Object getPrefValue(MetaPref mp) - { - if (mp.widgetIsTextField()) - { - JTextField textField = (JTextField) lookupComponent(mp, mp.getID() + IDENTIFIER_TEXT_FIELD); - // TODO 1 -- why doesnt this line work -- check flow for MetaPrefInt - // first! - String textFieldText = textField.getText(); - return mp.getInstance(textFieldText); - /* - * if (mp instanceof MetaPrefString) { return new String(textField.getText()); } else if (mp - * instanceof MetaPrefInt) { return new Integer(textField.getText()); } else if (mp instanceof - * MetaPrefFloat) { return new Float(textField.getText()); } - */ - } - else if (mp.widgetIsRadio()) - { - if (mp instanceof MetaPrefBoolean && !mp.hasChoices()) - { - JRadioButton yesButton = (JRadioButton) lookupComponent(mp, mp.getID() - + IDENTIFIER_BOOLEAN_YES); - MetaPref mpb = (MetaPrefBoolean) mp; - return mpb.getInstance(yesButton.isSelected()); - } - else - { - // TODO: if we could fetch the ButtonGroup, we could do - // this more efficiently. - // find the selected one and return it - ArrayList> choices = mp.getChoices(); - for (Choice choice : choices) - { - String regName = mp.getID() + choice.getName(); - JRadioButton choiceButton = (JRadioButton) lookupComponent(mp, regName); - if (choiceButton.isSelected()) - { - if (mp instanceof MetaPrefFloat) - return choice.getValue(); - else if (mp instanceof MetaPrefInt) - return choice.getValue(); - else if (mp instanceof MetaPrefBoolean) - return choice.getValue(); - else - return null; - } - } - } - } - else if (mp.widgetIsDropDown()) - { - if (mp instanceof MetaPrefFloat) - { - MetaPrefFloat mpf = (MetaPrefFloat) mp; - ArrayList> choices = mpf.getChoices(); - JComboBox comboBox = (JComboBox) lookupComponent(mp, mp.getID() + IDENTIFIER_DROPDOWN); - int selectedIndex = comboBox.getSelectedIndex(); - return new Float(choices.get(selectedIndex).getValue()); - } - else if (mp instanceof MetaPrefInt) - { - JComboBox comboBox = (JComboBox) lookupComponent(mp, mp.getID() + IDENTIFIER_DROPDOWN); - return new Integer(comboBox.getSelectedIndex()); - } - } - else if (mp.widgetIsCheckBox()) - { - JCheckBox checkBox = (JCheckBox) lookupComponent(mp, mp.getID() + IDENTIFIER_CHECK_BOX); - return new Boolean(checkBox.isSelected()); - } - else if (mp.widgetIsSlider()) - { - if (mp instanceof MetaPrefInt) - { - JSlider jSlider = (JSlider) lookupComponent(mp, mp.getID() + IDENTIFIER_SLIDER); - return new Integer(jSlider.getValue()); - } - else if (mp instanceof MetaPrefFloat) - { - JSlider jSlider = (JSlider) lookupComponent(mp, mp.getID() + IDENTIFIER_SLIDER); - int sliderValue = jSlider.getValue(); - return new Float(((float) sliderValue) / FLOAT_SLIDER_MODIFIER); - } - } - else if (mp.widgetIsSpinner()) - { - JSpinner jSpinner = (JSpinner) lookupComponent(mp, mp.getID() + IDENTIFIER_SPINNER); - if (mp instanceof MetaPrefInt) - return new Integer((Integer) jSpinner.getValue()); - else if (mp instanceof MetaPrefFloat) - return new Float((Float) jSpinner.getValue()); - } - else if (mp.widgetIsColorChooser()) - { - JColorChooser colorChooser = (JColorChooser) lookupComponent(mp, mp.getID() - + IDENTIFIER_COLOR_CHOOSER); - return colorChooser.getColor(); - } - else if (mp.widgetIsFileChooser()) - { - JFileChooser fileChooser = (JFileChooser) lookupComponent(mp, mp.getID() - + IDENTIFIER_FILE_CHOOSER); - return fileChooser.getSelectedFile(); - } - return null; - } - - /** - * Returns a JComponent from the ObjectRegistry by name - * - * @param mp - * metapref to look up - * @param labelAndName - * the label/name that was added to the metapref's id to identify a particular jComponent - * @return JComponent matching labelAndName from ObjectRegistry - */ - protected JComponent lookupComponent(MetaPref mp, String labelAndName) - { - // println("Trying to fetch: " + labelAndName); - JComponent jComponent = jCatComponentsMap(mp).get(labelAndName); - return jComponent; - } - - protected void savePrefs() - { - if (savePrefsPURL == null) - { - // TODO provide better feedback to the user here!!! - warning("Not saving Prefs persistently cause savePrefsURL == null."); - } - else - { - try - { - SimplTypesScope.serialize(prefSet, savePrefsPURL.file(), Format.XML); - } - catch (Exception e) - { - // TODO auto-generated catch block - e.printStackTrace(); - } - } - } - - /** - * Save the preferences; called by {@link #createApplyButton()} and {@link #createSaveButton()}. - * Saves the prefs to {@link #savePrefsPURL}. - */ - public void actionSavePreferences() - { - // update prefs - updatePrefsFromWidgets(); - - // save prefs back to the file - savePrefs(); - } - - /** - * Get the jContentPane for the editor. - * - * @return - */ - public JPanel getJContentPane() - { - return jContentPane; - } -} +/** + * + */ +package ecologylab.appframework.types.prefs.gui; + +import java.awt.GridBagConstraints; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.swing.Action; +import javax.swing.JCheckBox; +import javax.swing.JColorChooser; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JSlider; +import javax.swing.JSpinner; +import javax.swing.JTextField; +import javax.swing.SpinnerNumberModel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import ecologylab.appframework.types.prefs.Choice; +import ecologylab.appframework.types.prefs.MetaPref; +import ecologylab.appframework.types.prefs.MetaPrefBoolean; +import ecologylab.appframework.types.prefs.MetaPrefFloat; +import ecologylab.appframework.types.prefs.MetaPrefInt; +import ecologylab.appframework.types.prefs.MetaPrefSet; +import ecologylab.appframework.types.prefs.Pref; +import ecologylab.appframework.types.prefs.PrefSet; +import ecologylab.appframework.types.prefs.ValueChangedListener; +import ecologylab.collections.Scope; +import ecologylab.generic.Debug; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; + +/** + * Contains methods for creating widgets associated with Prefs. + * + * @author Zachary O. Toups (toupsz@cs.tamu.edu) + */ +public class PrefEditorWidgets extends Debug implements ChangeListener +{ + /** + * The string that will be added to the metapref's id, to create a unique identifier for a + * jComponent. + */ + static final String IDENTIFIER_CHECK_BOX = "checkBox"; + + /** + * The string that will be added to the metapref's id, to create a unique identifier for a + * jComponent. + */ + static final String IDENTIFIER_BOOLEAN_NO = "No"; + + /** + * The string that will be added to the metapref's id, to create a unique identifier for a + * jComponent. + */ + static final String IDENTIFIER_BOOLEAN_YES = "Yes"; + + /** + * The string that will be added to the metapref's id, to create a unique identifier for a + * jComponent. + */ + static final String IDENTIFIER_FILE_CHOOSER = "fileChooser"; + + /** + * The string that will be added to the metapref's id, to create a unique identifier for a + * jComponent. + */ + static final String IDENTIFIER_COLOR_CHOOSER = "colorChooser"; + + /** + * The string that will be added to the metapref's id, to create a unique identifier for a + * jComponent. + */ + public static final String IDENTIFIER_SPINNER = "spinner"; + + /** + * The string that will be added to the metapref's id, to create a unique identifier for a + * jComponent. + */ + static final String IDENTIFIER_SLIDER = "slider"; + + /** + * The string that will be added to the metapref's id, to create a unique identifier for a + * jComponent. + */ + static final String IDENTIFIER_DROPDOWN = "dropdown"; + + /** + * The string that will be added to the metapref's id, to create a unique identifier for a + * jComponent. + */ + static final String IDENTIFIER_TEXT_FIELD = "textField"; + + /** + * The amount by which floats should be multiplied for use with sliders. If this number is 10, you + * will be able to see the 1 digit after the decimal when the number is changed back (10.1). For + * 100, you will have 2 digits after the decimal (10.11). Etc. + */ + static final int FLOAT_SLIDER_MODIFIER = 10; + + /** + * The inset between the right side of the gui panel and the right side of values. + */ + protected static final int RIGHT_GUI_INSET = 20; + + /** + * The padding between the default value in a text field and either side of the text field. + */ + protected static final int TEXT_FIELD_PADDING = 50; + + /** + * Okay, this is really, really important. The map goes like this: CategoryName to (MetaPrefName + * to (Array of JComponents)) So for each category, you get a sorted map of the metaprefs in that + * category. From that map you can get a list of all the components for a metapref by name. + */ + protected HashMap>> jCatComponentsMap = new HashMap>>(); + + /** Set of MetaPrefs */ + protected MetaPrefSet metaPrefSet; + + /** Set of Prefs */ + protected PrefSet prefSet; + + /** PURL to save prefs.xml to */ + protected ParsedURL savePrefsPURL; + + /** + * Content pane within base window for GUI + */ + protected JPanel jContentPane; + + /** + * The base function that you call to construct the prefs editor GUI. This requires that the + * MetaPrefSet and PrefSet be instantiated and populated prior to call. This function creates the + * entire GUI and handles all actions for it. + * + * @param metaPrefSet + * Set of MetaPrefs + * @param prefSet + * Set of Prefs + * @param savePrefsPURL + * ParsedURL to save prefs.xml to + * @param isStandalone + * Whether or not we're calling this standalone + */ + public PrefEditorWidgets(MetaPrefSet metaPrefSet, PrefSet prefSet, ParsedURL savePrefsPURL) + { + this.metaPrefSet = metaPrefSet; + this.prefSet = prefSet; + this.savePrefsPURL = savePrefsPURL; + } + + /** + * Creates a text field. + * + * @param panel + * JPanel this field will be associated with. + * @param mp + * MetaPref this field is for. + * + * @return JTextField with properties initialized to parameters. + */ + protected JTextField createTextField(JPanel panel, MetaPref mp) + { + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.FIRST_LINE_START; + + JTextField textField = new JTextField(); + textField.setHorizontalAlignment(JTextField.CENTER); + textField.setText(mp.getDefaultValue().toString()); + textField.setName(IDENTIFIER_TEXT_FIELD); + c.gridx = 0; + c.gridy = 0; + c.insets = new Insets(0, 0, 0, RIGHT_GUI_INSET); // top,left,bottom,right + c.ipadx = TEXT_FIELD_PADDING; + + panel.add(textField, c); + + // add metapref's component to array + Scope mpComponents = jCatComponentsMap.get(mp.getCategory()).get(mp.getID()); + if (mpComponents != null) + { + registerComponent(mp, IDENTIFIER_TEXT_FIELD, textField); + } + + return textField; + } + + /** + * Creates a check box. + * + * @param panel + * JPanel this button will be associated with. + * @param mp + * MetaPref this checkbox is being created for. + * + * @return JCheckBox with properties initialized to parameters. + */ + protected JCheckBox createCheckBox(JPanel panel, MetaPref mp) + { + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.LINE_START; + + JCheckBox checkBox = new JCheckBox(); + + checkBox.setSelected((Boolean) mp.getDefaultValue()); + checkBox.setName(IDENTIFIER_CHECK_BOX); + c.gridx = 0; + c.gridy = 0; + c.insets = new Insets(0, 0, 0, RIGHT_GUI_INSET); // top,left,bottom,right + + panel.add(checkBox, c); + + // add metapref's component to array + Scope mpComponents = jCatComponentsMap.get(mp.getCategory()).get(mp.getID()); + if (mpComponents != null) + { + registerComponent(mp, IDENTIFIER_CHECK_BOX, checkBox); + } + + return checkBox; + } + + /** + * Creates a drop down menu; combo box. + * + * @param panel + * JPanel this field will be associated with. + * @param mp + * MetaPref this combo box is being created for. + * + * @return JComboBox with properties initialized to parameters. + */ + protected JComboBox createDropDown(JPanel panel, MetaPref mp) + { + ArrayList> choices = mp.getChoices(); + T defValue = mp.getDefaultValue(); + if (choices != null) + { + String[] choiceLabels = new String[choices.size()]; + int i = 0; + int selected = 0; + for (Choice choice : choices) + { + choiceLabels[i] = choice.getLabel(); + if (choice.getValue() == defValue) + selected = i; + i++; + } + + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.FIRST_LINE_START; + + JComboBox comboBox = new JComboBox(choiceLabels); + comboBox.setSelectedIndex(selected); + comboBox.setName(IDENTIFIER_DROPDOWN); + c.gridx = 0; + c.gridy = 0; + c.insets = new Insets(0, 0, 0, RIGHT_GUI_INSET); // top,left,bottom,right + c.ipadx = TEXT_FIELD_PADDING; + + panel.add(comboBox, c); + + // add metapref's component to array + Scope mpComponents = jCatComponentsMap.get(mp.getCategory()).get(mp.getID()); + if (mpComponents != null) + { + registerComponent(mp, IDENTIFIER_DROPDOWN, comboBox); + } + + return comboBox; + } + return null; + } + + /** + * Creates a slider. + * + * @param panel + * JPanel this slider will be associated with. + * @param mp + * MetaPref this slider is being created for. + * @param labelAndName + * Name of slider + * @param valuesAreAltered + * Whether or not the values of the metapref/pref need to be altered for the slider. + * @param valueAlteredBy + * How much the metapref/pref values are multiplied/ divided by. Only used if + * valuesAreAltered=true. + * + * @return JSlider with properties initialized to parameters. + */ + protected JSlider createSlider(JPanel panel, MetaPref mp, String labelAndName, + boolean valuesAreAltered, int valueAlteredBy) + { + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.LINE_START; + + JSlider jSlider = new JSlider(); + if (valuesAreAltered) + { + // values must be altered by the modifier parameter + int newMin = (int) ((Float) mp.getMinValue() * FLOAT_SLIDER_MODIFIER); + int newMax = (int) ((Float) mp.getMaxValue() * FLOAT_SLIDER_MODIFIER); + int defVal = (int) ((Float) mp.getDefaultValue() * FLOAT_SLIDER_MODIFIER); + jSlider.setMinimum(newMin); + jSlider.setMaximum(newMax); + jSlider.setValue(defVal); + jSlider.setMajorTickSpacing(FLOAT_SLIDER_MODIFIER * 5); + jSlider.setMinorTickSpacing(FLOAT_SLIDER_MODIFIER / 5); + Float curValue = new Float((float) (jSlider.getValue()) / FLOAT_SLIDER_MODIFIER); + jSlider.setToolTipText(curValue.toString()); + + // we need to mess with the labels so they display the correct + // values. + Hashtable labelTable = jSlider.createStandardLabels( + FLOAT_SLIDER_MODIFIER * 5, newMin); + // add a label for the max value to the table if one doesn't exist + // already + if (!labelTable.containsKey(newMax)) + { + Hashtable maxLabelTable = jSlider.createStandardLabels( + FLOAT_SLIDER_MODIFIER * 5, newMax); + labelTable.putAll(maxLabelTable); + } + for (Map.Entry entry : labelTable.entrySet()) + { + // changes here ARE reflected in labelTable + + // NOTE: this is the way you would change/remove entries from + // list of labels. + // you cannot add entries here. see the Java API and: + // http://java.sun.com/docs/books/tutorial/uiswing/components/slider.html + // for more details + JLabel label = (JLabel) entry.getValue(); + Float value = new Float(label.getText()); + value = value / FLOAT_SLIDER_MODIFIER; + label.setText(value.toString()); + } + jSlider.setLabelTable(labelTable); + jSlider.setName(labelAndName + "thisisafloat"); + } + else + { + // default behavior + jSlider.setMinimum((Integer) mp.getMinValue()); + jSlider.setMaximum((Integer) mp.getMaxValue()); + jSlider.setValue((Integer) mp.getDefaultValue()); + jSlider.setMajorTickSpacing(10); + jSlider.setMinorTickSpacing(1); + Integer curValue = jSlider.getValue(); + jSlider.setToolTipText(curValue.toString()); + jSlider.setName(labelAndName); + } + + jSlider.setPaintTicks(true); + jSlider.setPaintLabels(true); + jSlider.addChangeListener(this); + c.gridx = 0; + c.gridy = 0; + c.insets = new Insets(0, 0, 0, RIGHT_GUI_INSET); // top,left,bottom,right + panel.add(jSlider, c); + + // add metapref's component to array + Scope mpComponents = jCatComponentsMap.get(mp.getCategory()).get(mp.getID()); + if (mpComponents != null) + { + registerComponent(mp, labelAndName, jSlider); + } + + return jSlider; + } + + /** + * Creates a spinner. This is a text field with up/down arrows that allow you to increase/decrease + * the value in the text box. + * + * @param panel + * JPanel this spinner will be associated with. + * @param mp + * MetaPref this spinner is being created for. + * + * @return JSpinner with properties initialized to parameters. + */ + protected JSpinner createSpinner(JPanel panel, MetaPref mp) + { + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.LINE_START; + + double stepSize = 1.0; + if (mp instanceof MetaPrefFloat) + stepSize = 0.1; + + SpinnerNumberModel numModel = new SpinnerNumberModel(); + numModel.setMinimum((Float) mp.getMinValue()); + numModel.setMaximum((Float) mp.getMaxValue()); + numModel.setValue(mp.getDefaultValue()); + numModel.setStepSize(stepSize); + + JSpinner jSpinner = new JSpinner(); + jSpinner.setModel(numModel); + jSpinner.setValue(mp.getDefaultValue()); + jSpinner.setName(IDENTIFIER_SPINNER); + c.gridx = 0; + c.gridy = 0; + c.insets = new Insets(0, 0, 0, RIGHT_GUI_INSET); // top,left,bottom,right + panel.add(jSpinner, c); + + // add metapref's component to array + Scope mpComponents = jCatComponentsMap.get(mp.getCategory()).get(mp.getID()); + if (mpComponents != null) + { + registerComponent(mp, IDENTIFIER_SPINNER, jSpinner); + } + + return jSpinner; + } + + /** + * Returns the ObjectRegistry for this MetaPref's jComponents. + * + * @param mp + * MetaPref whose jComponents we want. + * + * @return ObjectRegistry for MetaPref's jComponents. + */ + protected Scope jCatComponentsMap(MetaPref mp) + { + LinkedHashMap> categoryMap = this.jCatComponentsMap.get(mp + .getCategory()); + + if (categoryMap == null) + { + categoryMap = new LinkedHashMap>(); + this.jCatComponentsMap.put(mp.getCategory(), categoryMap); + } + + Scope result = categoryMap.get(mp.getID()); + if (result == null) + { + LinkedHashMap> catHash = jCatComponentsMap.get(mp.getCategory()); + result = new Scope(); + catHash.put(mp.getID(), result); + } + return result; + } + + /** + * Registers a JComponent with the ObjectRegistry + * + * @param mp + * metapref we want to register + * @param labelAndName + * label/name to add to the metapref's id to identify a particular jComponent. must be + * UNIQUE. + * @param jComponent + * jComponent to register + */ + public void registerComponent(MetaPref mp, String labelAndName, JComponent jComponent) + { + // println("Registering: " + this.id+labelAndName); + jCatComponentsMap(mp).put(mp.getID() + labelAndName, jComponent); + } + + /** + * This is for sliders; when we move the slider, we need to update the tooltip and force it to + * display. TODO: change placement of tooltip + */ + public void stateChanged(ChangeEvent e) + { + JSlider source = (JSlider) e.getSource(); + String name = source.getName(); + Float curVal = new Float(source.getValue()); + if (name.indexOf("thisisafloat") != -1) + { + curVal = curVal / FLOAT_SLIDER_MODIFIER; + source.setToolTipText(curVal.toString()); + } + else + { + source.setToolTipText(curVal.toString()); + } + Action action = source.getActionMap().get("postTip"); + if (action != null) + { + // show me the tooltip, NOW + action.actionPerformed(new ActionEvent(source, ActionEvent.ACTION_PERFORMED, "postTip")); + } + } + + /** + * Queries all widgets and updates their associated Prefs; this will cascade and cause each Pref + * to notify all PrefChangedListeners associated with Pref. + */ + public void updatePrefsFromWidgets() + { + /* + * we do this with metaprefs because we will always have all metaprefs. we may not always have a + * prefs file to start with. + */ + // this iterator organizes them by category + for (String cat : metaPrefSet.getCategories()) + { + for (MetaPref mp : metaPrefSet.getMetaPrefListByCategory(cat)) + { + Pref pref = mp.getAssociatedPref(); + Object editedValue = getPrefValue(mp); + if (editedValue == null) + { + Debug.error(this, "edited value = null for: " + mp.getID()); + } + else + { + Object previousValue = pref.value(); + pref.setValue(editedValue); + + // TODO probably take this code out; now setValue will notify + // all PrefChangedListeners that are registered with it. + ValueChangedListener valueChangedListener = mp.getValueChangedListener(); + if ((valueChangedListener != null) && (editedValue != null)) + { + if (!editedValue.equals(previousValue)) + valueChangedListener.valueChanged(pref); + } + + if (!prefSet.containsKey(pref.key())) + prefSet.add(pref); + } + } + } + } + + /** + * Get the pref value (if applicable) for a given metapref. + * + * @param mp + * metapref to fetch pref value for + * @return pref value or null + */ + Object getPrefValue(MetaPref mp) + { + if (mp.widgetIsTextField()) + { + JTextField textField = (JTextField) lookupComponent(mp, mp.getID() + IDENTIFIER_TEXT_FIELD); + // TODO 1 -- why doesnt this line work -- check flow for MetaPrefInt + // first! + String textFieldText = textField.getText(); + return mp.getInstance(textFieldText); + /* + * if (mp instanceof MetaPrefString) { return new String(textField.getText()); } else if (mp + * instanceof MetaPrefInt) { return new Integer(textField.getText()); } else if (mp instanceof + * MetaPrefFloat) { return new Float(textField.getText()); } + */ + } + else if (mp.widgetIsRadio()) + { + if (mp instanceof MetaPrefBoolean && !mp.hasChoices()) + { + JRadioButton yesButton = (JRadioButton) lookupComponent(mp, mp.getID() + + IDENTIFIER_BOOLEAN_YES); + MetaPref mpb = (MetaPrefBoolean) mp; + return mpb.getInstance(yesButton.isSelected()); + } + else + { + // TODO: if we could fetch the ButtonGroup, we could do + // this more efficiently. + // find the selected one and return it + ArrayList> choices = mp.getChoices(); + for (Choice choice : choices) + { + String regName = mp.getID() + choice.getName(); + JRadioButton choiceButton = (JRadioButton) lookupComponent(mp, regName); + if (choiceButton.isSelected()) + { + if (mp instanceof MetaPrefFloat) + return choice.getValue(); + else if (mp instanceof MetaPrefInt) + return choice.getValue(); + else if (mp instanceof MetaPrefBoolean) + return choice.getValue(); + else + return null; + } + } + } + } + else if (mp.widgetIsDropDown()) + { + if (mp instanceof MetaPrefFloat) + { + MetaPrefFloat mpf = (MetaPrefFloat) mp; + ArrayList> choices = mpf.getChoices(); + JComboBox comboBox = (JComboBox) lookupComponent(mp, mp.getID() + IDENTIFIER_DROPDOWN); + int selectedIndex = comboBox.getSelectedIndex(); + return new Float(choices.get(selectedIndex).getValue()); + } + else if (mp instanceof MetaPrefInt) + { + JComboBox comboBox = (JComboBox) lookupComponent(mp, mp.getID() + IDENTIFIER_DROPDOWN); + return new Integer(comboBox.getSelectedIndex()); + } + } + else if (mp.widgetIsCheckBox()) + { + JCheckBox checkBox = (JCheckBox) lookupComponent(mp, mp.getID() + IDENTIFIER_CHECK_BOX); + return new Boolean(checkBox.isSelected()); + } + else if (mp.widgetIsSlider()) + { + if (mp instanceof MetaPrefInt) + { + JSlider jSlider = (JSlider) lookupComponent(mp, mp.getID() + IDENTIFIER_SLIDER); + return new Integer(jSlider.getValue()); + } + else if (mp instanceof MetaPrefFloat) + { + JSlider jSlider = (JSlider) lookupComponent(mp, mp.getID() + IDENTIFIER_SLIDER); + int sliderValue = jSlider.getValue(); + return new Float(((float) sliderValue) / FLOAT_SLIDER_MODIFIER); + } + } + else if (mp.widgetIsSpinner()) + { + JSpinner jSpinner = (JSpinner) lookupComponent(mp, mp.getID() + IDENTIFIER_SPINNER); + if (mp instanceof MetaPrefInt) + return new Integer((Integer) jSpinner.getValue()); + else if (mp instanceof MetaPrefFloat) + return new Float((Float) jSpinner.getValue()); + } + else if (mp.widgetIsColorChooser()) + { + JColorChooser colorChooser = (JColorChooser) lookupComponent(mp, mp.getID() + + IDENTIFIER_COLOR_CHOOSER); + return colorChooser.getColor(); + } + else if (mp.widgetIsFileChooser()) + { + JFileChooser fileChooser = (JFileChooser) lookupComponent(mp, mp.getID() + + IDENTIFIER_FILE_CHOOSER); + return fileChooser.getSelectedFile(); + } + return null; + } + + /** + * Returns a JComponent from the ObjectRegistry by name + * + * @param mp + * metapref to look up + * @param labelAndName + * the label/name that was added to the metapref's id to identify a particular jComponent + * @return JComponent matching labelAndName from ObjectRegistry + */ + protected JComponent lookupComponent(MetaPref mp, String labelAndName) + { + // println("Trying to fetch: " + labelAndName); + JComponent jComponent = jCatComponentsMap(mp).get(labelAndName); + return jComponent; + } + + protected void savePrefs() + { + if (savePrefsPURL == null) + { + // TODO provide better feedback to the user here!!! + warning("Not saving Prefs persistently cause savePrefsURL == null."); + } + else + { + try + { + SimplTypesScope.serialize(prefSet, savePrefsPURL.file(), Format.XML); + } + catch (Exception e) + { + // TODO auto-generated catch block + e.printStackTrace(); + } + } + } + + /** + * Save the preferences; called by {@link #createApplyButton()} and {@link #createSaveButton()}. + * Saves the prefs to {@link #savePrefsPURL}. + */ + public void actionSavePreferences() + { + // update prefs + updatePrefsFromWidgets(); + + // save prefs back to the file + savePrefs(); + } + + /** + * Get the jContentPane for the editor. + * + * @return + */ + public JPanel getJContentPane() + { + return jContentPane; + } +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/gui/PrefsEditor.java b/simplSunSpecifics/src/ecologylab/appframework/types/prefs/gui/PrefsEditor.java similarity index 97% rename from simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/gui/PrefsEditor.java rename to simplSunSpecifics/src/ecologylab/appframework/types/prefs/gui/PrefsEditor.java index 5ce5d69f..4abf25f2 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/gui/PrefsEditor.java +++ b/simplSunSpecifics/src/ecologylab/appframework/types/prefs/gui/PrefsEditor.java @@ -1,1204 +1,1204 @@ -package ecologylab.appframework.types.prefs.gui; - -import java.awt.Color; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; -import java.io.File; -import java.util.ArrayList; -import java.util.LinkedHashMap; - -import javax.swing.ButtonGroup; -import javax.swing.ButtonModel; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JColorChooser; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JScrollPane; -import javax.swing.JSeparator; -import javax.swing.JSlider; -import javax.swing.JSpinner; -import javax.swing.JTabbedPane; -import javax.swing.JTextField; -import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; -import javax.swing.ToolTipManager; - -import ecologylab.appframework.PropertiesAndDirectories; -import ecologylab.appframework.types.prefs.Choice; -import ecologylab.appframework.types.prefs.ChoiceBoolean; -import ecologylab.appframework.types.prefs.MetaPref; -import ecologylab.appframework.types.prefs.MetaPrefBoolean; -import ecologylab.appframework.types.prefs.MetaPrefFloat; -import ecologylab.appframework.types.prefs.MetaPrefInt; -import ecologylab.appframework.types.prefs.MetaPrefSet; -import ecologylab.appframework.types.prefs.Pref; -import ecologylab.appframework.types.prefs.PrefSet; -import ecologylab.collections.Scope; -import ecologylab.generic.Debug; -import ecologylab.generic.RestrictedFileSystemView; -import ecologylab.io.Assets; -import ecologylab.net.ParsedURL; - -/** - * Create the GUI for preference editing; also responsible for all - * actions associated with the GUI. - * - * @author Cae - * - */ -public class PrefsEditor -extends PrefEditorWidgets -implements WindowListener -{ - - /** - * The number of characters/columns at which the tooltips will try to wrap. - * Actual wrapping will be the nearest space AFTER this number. - */ - private static final int TOOLTIP_WRAP_WIDTH = 80; - /** - * A small inset for the top of an object in the GUI - */ - private static final int SMALL_TOP_GUI_INSET = 0; - /** - * The inset between the left side of the gui panel and the left - * side of the descriptions. - */ - private static final int LEFT_GUI_INSET = 20; - /** - * The inset between the top side of the gui panel and the object above it. - */ - private static final int TOP_GUI_INSET = 10; - /** - * The inset between the bottom of the gui section and the top of the - * next object. - */ - private static final int BOTTOM_GUI_INSET = 10; - - // base setup for gui - /** - * Base window for the GUI - */ - JFrame jFrame = null; - /** - * Cancel button for GUI - */ - JButton cancelButton = null; - /** - * Save button for GUI - */ - JButton saveButton = null; - /** - * Apply button for GUI - */ - JButton applyButton = null; - /** - * Revert button for GUI - */ - JButton revertButton = null; - /** - * Tabbed pane within content pane within base window for GUI - */ - JTabbedPane jTabbedPane = null; - - /** - * Whether we're called this standalone or not - */ - boolean isStandalone; - - /** - * Start location on the screen for the gui - */ - static Point startLocation = new Point(100,100); - - /** - * Color picker; static so we only have one. - */ - static JColorChooser colorChooser = new JColorChooser(); - static JDialog colorChooserDialog; - - /** - * File chooser; static so we only have one. - * Instantiation is performed within a static block for error handling. - * If the standard JFileChooser cannot open due to an exception, as described in the Bug listing - */ - static JFileChooser fileChooser; - - static - { - try - { - fileChooser = new JFileChooser(PropertiesAndDirectories.desktopDir()); - } - catch(Exception e) - { - Debug.println("Using RestrictedFileSystemView for PrefsEditor JFileChooser"); - fileChooser = new JFileChooser(PropertiesAndDirectories.desktopDir(), new RestrictedFileSystemView()); - } - } - - /** - * File dialog; static so we only have one. - */ - static JDialog fileChooserDialog; - - /** - * The base function that you call to construct the prefs editor GUI. - * This requires that the MetaPrefSet and PrefSet be instantiated and populated - * prior to call. This function creates the entire GUI and handles all actions - * for it. - * - * @param metaPrefSet Set of MetaPrefs - * @param prefSet Set of Prefs - * @param savePrefsPURL ParsedURL to save prefs.xml to - * @param isStandalone Whether or not we're calling this standalone - */ - public PrefsEditor(MetaPrefSet metaPrefSet, PrefSet prefSet, ParsedURL savePrefsPURL, final boolean createJFrame, final boolean isStandalone) - { - super (metaPrefSet, prefSet, savePrefsPURL); - - this.isStandalone = isStandalone; - - setupContainer(createJFrame, isStandalone); - } - - /** - * Calls createJFrame - * @see #createJFrame() - * @return Base window (JFrame) for the GUI - */ - public Container setupContainer(final boolean createJFrame, final boolean isStandalone) - { - Container result = createContainer(createJFrame); - if (createJFrame) - { - jFrame.addWindowListener(new WindowAdapter() - { - @Override public void windowClosing(WindowEvent e) - { - closeWindow(); - } - }); - jFrame.setVisible(true); - } - return result; - } - - /** - * Create the base window for the GUI. - * - * This contains {@link #createJContentPane()}. - * - * This is a static part of the GUI. - * - * @return Base window (JFrame) for the GUI - */ - // static bits of gui - private Container createContainer(boolean createJFrame) - { - Container result = null; - if (createJFrame) - { - if (jFrame == null) - { - jFrame = new JFrame(); - jFrame.setContentPane(createJContentPane()); - jFrame.addWindowListener(this); - String title = metaPrefSet.getTitle(); - if (title == null) - title = "Preferences Editor"; - jFrame.setTitle(title); - } - result = jFrame; - } - else - { - result = createJContentPane(); - } - setSize(result); - return result; - } - - private void setSize(Container jContainer) - { - int width = metaPrefSet.getWidth(); - if (width == 0) - width = 603; - int height = metaPrefSet.getHeight(); - if (height == 0) - height = 532; - jContainer.setPreferredSize(new Dimension(width, height)); - jContainer.setSize(new Dimension(width, height)); - } - - /** - * Function to close the window - */ - private void closeWindow() - { - if (jFrame != null) - { - jFrame.setVisible(false); - jFrame.dispose(); - } - if (PrefsEditor.this.isStandalone) - System.exit(0); - } - - /** - * Function to close the window - */ - private void saveLocation() - { - startLocation = jFrame.getLocation(); - } - - /** - * Create the content pane within the base window for the GUI. - * - * This is contained within {@link #createJFrame()}. - * This contains {@link #createApplyButton()}, {@link #createCancelButton()}, - * and {@link #createRevertButton()}, {@link #createSaveButton()}, - * and {@link #createJTabbedPane()}. - * - * This is a static part of the GUI. - * - * @return Content pane (JPanel) within the base window for the GUI - */ - private JPanel createJContentPane() - { - if (jContentPane == null) - { - jContentPane = new JPanel(); - jContentPane.setLayout(null); - jContentPane.add(createJTabbedPane(), null); - jContentPane.add(createCancelButton(), null); - jContentPane.add(createSaveButton(), null); - jContentPane.add(createApplyButton(), null); - jContentPane.add(createRevertButton(), null); - } - return jContentPane; - } - - /** - * Create the cancel button for the GUI. This button closes - * the window without saving the prefs. - * This is contained within {@link #createJContentPane()}. - * This is a static part of the GUI. - * - * @return Cancel button (JButton) for GUI - */ - private JButton createCancelButton() - { - if (cancelButton == null) - { - cancelButton = new JButton(); - cancelButton.setBounds(new Rectangle(482, 435, 89, 35)); - cancelButton.setText("Cancel"); - cancelButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - saveLocation(); - closeWindow(); - } - }); - } - return cancelButton; - } - - /** - * Create the save button for the GUI. This button saves - * prefs and closes the window. - * - * This is contained within {@link #createJContentPane()}. - * This contains {@link #actionSavePreferences()}. - * - * This is a static part of the GUI. - * - * @return Save button (JButton) for GUI - */ - JButton createSaveButton() - { - if (saveButton == null) - { - saveButton = new JButton(); - saveButton.setBounds(new Rectangle(379, 435, 89, 35)); - saveButton.setText("Save"); - saveButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - saveLocation(); - actionSavePreferences(); - closeWindow(); - } - }); - } - return saveButton; - } - - /** - * Create the apply button for the GUI. This saves the prefs - * and doesn't close the window. - * - * This is contained within {@link #createJContentPane()}. - * This contains {@link #actionSavePreferences()}. - * - * This is a static part of the GUI. - * - * @return Apply button (JButton) for GUI - */ - JButton createApplyButton() - { - if (applyButton == null) - { - applyButton = new JButton(); - applyButton.setBounds(new Rectangle(276, 435, 89, 35)); - applyButton.setText("Apply"); - applyButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - actionSavePreferences(); - } - }); - } - return applyButton; - } - - /** - * Create the revert button for the GUI. This reverts the - * prefs to their default values when pressed. - * - * This is contained within {@link #createJContentPane()}. - * This contains {@link #actionRevertPreferencesToDefault()}. - * - * This is a static part of the GUI. - * - * @return Revert button (JButton) for GUI - */ - private JButton createRevertButton() - { - if (revertButton == null) - { - revertButton = new JButton(); - revertButton.setBounds(new Rectangle(15, 435, 137, 35)); - revertButton.setText("Revert to Default"); - revertButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - actionRevertPreferencesToDefault(); - } - }); - } - return revertButton; - } - // end of static bits of gui - - // bits of gui that are all or part auto-generated - /** - * Create the tabbed pane within the main frame within the main - * window of the GUI. This pane contains the content panes which define - * the actual tabs of the GUI. - * - * This is contained within {@link #createJContentPane()}. - * This contains {@link #getTabbedBodyFrame(String, JScrollPane)}. - * - * This function includes xml-dependent code. - * - * @return Tabbed pane within which the tabs for the GUI are defined - */ - private JTabbedPane createJTabbedPane() - { - if (jTabbedPane == null) - { - jTabbedPane = new JTabbedPane(); - jTabbedPane.setName("jTabbedPane"); - jTabbedPane.setBounds(new Rectangle(0, 0, 595, 416)); - - String[] orderedTabNames = new String[metaPrefSet.getNumberOfTabs()]; - metaPrefSet.getOrderedTabNames(orderedTabNames); - for (String cat : orderedTabNames) - { - JScrollPane scrollPane = new JScrollPane(); - scrollPane.setSize(new Dimension(jTabbedPane.getWidth(),jTabbedPane.getHeight())); - scrollPane.setComponentOrientation(java.awt.ComponentOrientation.LEFT_TO_RIGHT); - scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); - scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - scrollPane.setName(cat); - scrollPane.setViewportView(getTabbedBodyFrame(cat,scrollPane)); - jTabbedPane.addTab(cat, null, scrollPane, null); - - // add category to components map - LinkedHashMap> catHash = jCatComponentsMap.get(cat); - if (catHash == null) - { - catHash = new LinkedHashMap>(); - jCatComponentsMap.put(cat, catHash); - //System.err.print("Adding: " + cat + '\n'); - } - } - } - return jTabbedPane; - } - - /** - * The actual tab for a category within the GUI. - * - * This is contained within {@link #createJTabbedPane()} - * This contains {@link #createDescriptionSection(JPanel, GridBagConstraints, int, MetaPref)}, - * and {@link #createWidgetFromMetaPref(GridBagConstraints, MetaPref, int)}, - * and {@link #createSeparator(GridBagConstraints, int)}. - * - * This function includes xml-dependent code. - * - * @param category Name of category - * @param scrollPane The pane that scrolls within this panel - * - * @return Tab for a category within the GUI - */ - @SuppressWarnings("serial") - private JPanel getTabbedBodyFrame(String category, JScrollPane scrollPane) - { - JPanel contentPanel = new JPanel() - { - private boolean firstTime = true; - @Override public void paintComponent(Graphics g) - { - if (firstTime) - { - firstTime = false; - int numberOfEntries = this.getComponentCount(); - for (int i=0; i < numberOfEntries; i+=3) - { - // TODO: this only works because we alternate adding JLabels and JPanels and JSeparators - if ((this.getComponent(i) instanceof JLabel) && (this.getComponent(i+1) instanceof JPanel) && (this.getComponent(i+2) instanceof JSeparator)) - { - JLabel desc = (JLabel)this.getComponent(i); - JPanel val = (JPanel)this.getComponent(i+1); - JSeparator sep = (JSeparator)this.getComponent(i+2); - - FontMetrics fm = desc.getFontMetrics(desc.getFont()); - int actualWidth = (this.getWidth()-val.getWidth())-LEFT_GUI_INSET; - int stringWidth = SwingUtilities.computeStringWidth(fm, desc.getText()); - - desc.setPreferredSize(new Dimension(actualWidth,((stringWidth/actualWidth)+1)*fm.getHeight())); - sep.setPreferredSize(new Dimension(this.getWidth()-(LEFT_GUI_INSET*2),3)); - if (i+3 == numberOfEntries) - { - // make last separator invisible - sep.setVisible(false); - } - } - } - } - super.paintComponent(g); - } - }; - - // make tooltips display quickly - ToolTipManager.sharedInstance().setInitialDelay(10); - contentPanel.setLayout(new GridBagLayout()); - contentPanel.setMaximumSize(new Dimension(scrollPane.getWidth(),Integer.MAX_VALUE)); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.weightx = 0.1; - int rowNum = 0; - for (MetaPref metaPref : metaPrefSet.getMetaPrefListByCategory(category)) - { - // add metapref to components map - //System.err.print(category + '\n' + metaPref.getID() + '\n'); - LinkedHashMap> catHash = jCatComponentsMap.get(category); - if (catHash == null) - { - catHash = new LinkedHashMap>(); - jCatComponentsMap.put(category, catHash); - } - Scope mpComponentRegistry = catHash.get(metaPref.getID()); - if (mpComponentRegistry == null) - { - mpComponentRegistry = new Scope(); - catHash.put(metaPref.getID(), mpComponentRegistry); - } - - JLabel subDescription = createDescriptionSection(contentPanel, constraints, rowNum, metaPref); - JPanel subValue = createWidgetFromMetaPref(constraints, metaPref, rowNum); - - subValue.setMaximumSize(new Dimension(scrollPane.getWidth()/2,100)); - subDescription.setMaximumSize(new Dimension(scrollPane.getWidth()/2,50)); - - // we have to do this in order for our redraw code to work properly. - subDescription.setPreferredSize(new Dimension(1,1)); - - //add these suckers to the contentpanel. - constraints.anchor = GridBagConstraints.FIRST_LINE_START; - contentPanel.add(subDescription, constraints); - if (subValue != null) - { - constraints.anchor = GridBagConstraints.FIRST_LINE_END; - contentPanel.add(subValue, constraints); - } - JSeparator separator = createSeparator(constraints, rowNum); - constraints.anchor = GridBagConstraints.NORTH; - contentPanel.add(separator,constraints); - rowNum++; - } - - return contentPanel; - } - - /** - * Create the UI component (aka widget) that enables the user to manipulate the value of the preference. - * This is contained within {@link #getTabbedBodyFrame(String, JScrollPane)}. - * This function includes xml-dependent code. - * - * @param constraints GridBagConstraints - insets, row, col, etc - * @param metaPref Description of what widget type to use, default values, ... - * @param rowNum Row number for GridBagLayout - * - * @return JLabel Value section - */ - private JPanel createWidgetFromMetaPref(GridBagConstraints constraints, MetaPref metaPref, int rownum) - { - JPanel panel = new JPanel(); - panel.setName(metaPref.getID()); - panel.setLayout(new GridBagLayout()); - - if (metaPref.widgetIsTextField()) - { - createTextField(panel, metaPref); - } - else if (metaPref.widgetIsRadio()) - { - if (metaPref instanceof MetaPrefBoolean && !metaPref.hasChoices()) - { - createYesNoBooleanRadio((MetaPrefBoolean) metaPref, panel); - } - else - { - createChoicesBasedRadio(metaPref, panel); - } - } - else if (metaPref.widgetIsDropDown()) - { - createDropDown(panel, metaPref); - } - else if (metaPref.widgetIsCheckBox()) - { - createCheckBox(panel, metaPref); - } - else if (metaPref.widgetIsSlider()) - { - if (metaPref instanceof MetaPrefInt) - { - createSlider(panel, metaPref, IDENTIFIER_SLIDER, false, 0); - } - else if (metaPref instanceof MetaPrefFloat) - { - createSlider(panel, metaPref, IDENTIFIER_SLIDER, true, FLOAT_SLIDER_MODIFIER); - } - } - else if (metaPref.widgetIsSpinner()) - { - createSpinner(panel, metaPref); - } - else if (metaPref.widgetIsColorChooser()) - { - createColorChooser(panel, metaPref); - } - else if (metaPref.widgetIsFileChooser()) - { - createFileButton(metaPref, panel); - } - - panel.setVisible(true); - - if (panel != null) - { - constraints.gridx = 1; - constraints.gridy = rownum; - constraints.gridwidth = 1; - constraints.insets = new Insets(TOP_GUI_INSET,LEFT_GUI_INSET,BOTTOM_GUI_INSET,0); // top,left,bottom,right - // if we have a prefs value, override it now - if (Pref.hasPref(metaPref.getID())) - { - setWidgetToPrefValue(metaPref, Pref.lookupPref(metaPref.getID())); - } - } - return panel; - } - - /** - * Set the metapref's widget in the prefs editor to the value in - * the prefs xml file. - * - * @param mp metapref - * @param pref pref to set metapref's widget to - */ - private void setWidgetToPrefValue(MetaPref mp, Pref pref) - { - if (mp.widgetIsTextField()) - { - JTextField textField = (JTextField)lookupComponent(mp, mp.getID()+IDENTIFIER_TEXT_FIELD); - textField.setText(pref.value().toString()); - } - else if (mp.widgetIsRadio()) - { - if (mp instanceof MetaPrefBoolean && !mp.hasChoices()) - { - boolean prefValue = (Boolean)pref.value(); - if (prefValue) - { - JRadioButton yesButton = (JRadioButton)lookupComponent(mp, mp.getID()+IDENTIFIER_BOOLEAN_YES); - ButtonModel yesModel = yesButton.getModel(); - yesModel.setSelected(true); - } - else - { - JRadioButton noButton = (JRadioButton)lookupComponent(mp, mp.getID()+IDENTIFIER_BOOLEAN_NO); - ButtonModel noModel = noButton.getModel(); - noModel.setSelected(true); - } - } - else - { - // registered name - String regName = mp.getID() + mp.getChoiceNameByValue(pref.value().toString()); - JRadioButton defaultButton = (JRadioButton) lookupComponent(mp,regName); - ButtonModel buttonModel = defaultButton.getModel(); - buttonModel.setSelected(true); - } - } - else if (mp.widgetIsDropDown()) - { - JComboBox comboBox = (JComboBox)lookupComponent(mp, mp.getID() + IDENTIFIER_DROPDOWN); - comboBox.setSelectedIndex(mp.getIndexByValue(pref.value().toString())); - } - else if (mp.widgetIsCheckBox()) - { - JCheckBox checkBox = (JCheckBox)lookupComponent(mp, mp.getID() + IDENTIFIER_CHECK_BOX); - checkBox.setSelected((Boolean)pref.value()); - } - else if (mp.widgetIsSlider()) - { - if (mp instanceof MetaPrefInt) - { - Integer prefValue = (Integer)pref.value(); - JSlider jSlider = (JSlider)lookupComponent(mp,mp.getID()+IDENTIFIER_SLIDER); - jSlider.setValue(prefValue); - } - else if (mp instanceof MetaPrefFloat) - { - Float prefValue = (Float)pref.value(); - JSlider jSlider = (JSlider)lookupComponent(mp,mp.getID()+IDENTIFIER_SLIDER); - jSlider.setValue((int)(prefValue*FLOAT_SLIDER_MODIFIER)); - } - } - else if (mp.widgetIsSpinner()) - { - JSpinner jSpinner = (JSpinner)lookupComponent(mp,mp.getID()+IDENTIFIER_SPINNER); - jSpinner.setValue(pref.value()); - } - else if (mp.widgetIsColorChooser()) - { - Color prefValue = (Color)pref.value(); - JColorChooser colorChooser = (JColorChooser)lookupComponent(mp,mp.getID()+IDENTIFIER_COLOR_CHOOSER); - if (colorChooser != null) - { - colorChooser.setColor(prefValue); - } - } - else if (mp.widgetIsFileChooser()) - { - JFileChooser fileChooser = (JFileChooser)lookupComponent(mp,mp.getID()+IDENTIFIER_FILE_CHOOSER); - fileChooser.setSelectedFile((File)pref.value()); - } - } - - /** - * Revert the metapref's widget to the default value for it, defined - * in the metaprefs xml file. - * - * @param mp metapref to revert - */ - private void revertToDefault(MetaPref mp) - { - if (mp.widgetIsTextField()) - { - JTextField textField = (JTextField)lookupComponent(mp, mp.getID()+IDENTIFIER_TEXT_FIELD); - textField.setText(mp.getDefaultValue().toString()); - } - else if (mp.widgetIsRadio()) - { - if (mp instanceof MetaPrefBoolean && !mp.hasChoices()) - { - // get button - JRadioButton yesButton = (JRadioButton)lookupComponent(mp, mp.getID()+IDENTIFIER_BOOLEAN_YES); - ButtonModel yesModel = yesButton.getModel(); - boolean yesVal = (Boolean)mp.getDefaultValue(); - - if (yesVal) - { - yesModel.setSelected(true); - } - else - { - JRadioButton noButton = (JRadioButton)lookupComponent(mp, mp.getID()+IDENTIFIER_BOOLEAN_NO); - ButtonModel noModel = noButton.getModel(); - noModel.setSelected(true); - } - } - else - { - String regName = mp.getID() + mp.getChoiceNameByValue(mp.getDefaultValue().toString()); - //println("we think the name is: " + regName); - JRadioButton defaultButton = (JRadioButton)lookupComponent(mp,regName); - ButtonModel buttonModel = defaultButton.getModel(); - buttonModel.setSelected(true); - } - } - else if (mp.widgetIsDropDown()) - { - JComboBox comboBox = (JComboBox)lookupComponent(mp,mp.getID()+IDENTIFIER_DROPDOWN); - comboBox.setSelectedIndex(mp.getIndexByValue(mp.getDefaultValue().toString())); - } - else if (mp.widgetIsCheckBox()) - { - JCheckBox checkBox = (JCheckBox)lookupComponent(mp, mp.getID() + IDENTIFIER_CHECK_BOX); - checkBox.setSelected((Boolean)mp.getDefaultValue()); - } - else if (mp.widgetIsSlider()) - { - if (mp instanceof MetaPrefInt) - { - JSlider jSlider = (JSlider)lookupComponent(mp,mp.getID()+IDENTIFIER_SLIDER); - jSlider.setValue((Integer)mp.getDefaultValue()); - } - else if (mp instanceof MetaPrefFloat) - { - int alteredDefault = (int)((Float)mp.getDefaultValue()*FLOAT_SLIDER_MODIFIER); - JSlider jSlider = (JSlider)lookupComponent(mp,mp.getID()+IDENTIFIER_SLIDER); - jSlider.setValue(alteredDefault); - } - } - else if (mp.widgetIsSpinner()) - { - JSpinner jSpinner = (JSpinner)lookupComponent(mp,mp.getID()+IDENTIFIER_SPINNER); - jSpinner.setValue(mp.getDefaultValue()); - } - else if (mp.widgetIsColorChooser()) - { - JColorChooser colorChooser = (JColorChooser)lookupComponent(mp,mp.getID()+IDENTIFIER_COLOR_CHOOSER); - colorChooser.setColor((Color)mp.getDefaultValue()); - } - else if (mp.widgetIsFileChooser()) - { - JFileChooser fileChooser = (JFileChooser)lookupComponent(mp,mp.getID()+IDENTIFIER_FILE_CHOOSER); - fileChooser.setSelectedFile((File)mp.getDefaultValue()); - } - } - - /** - * The function that actually performs the revert-to-default actions - * is in the MetaPrefType classes. - */ - private void actionRevertPreferencesToDefault() - { - for (String cat : metaPrefSet.getCategories()) - { - for (MetaPref mp : metaPrefSet.getMetaPrefListByCategory(cat)) - { - revertToDefault(mp); - } - } - } - // end of gui actions for buttons - - /** - * Creates a separator to go between two preferences in the GUI. - * This is contained within {@link #getTabbedBodyFrame(String, JScrollPane)}. - * This function includes xml-dependent code. - * - * @param constraints GridBagConstraints - insets, row, col, etc - * @param rowNum Row number for GridBagLayout - * - * @return JSeparator for tab frame in GUI - */ - private JSeparator createSeparator(GridBagConstraints constraints, int rowNum) - { - JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL); - constraints.gridx = 0; - constraints.gridy = rowNum + 1; - constraints.gridwidth = 2; - constraints.insets = new Insets(SMALL_TOP_GUI_INSET,0,0,0); - return separator; - } - - /** - * Create the description section for a preference. - * - * This is contained within {@link #getTabbedBodyFrame(String, JScrollPane)}. - * This contains {@link #createLabel(JPanel, MetaPref, int, int)}. - * - * This function includes xml-dependent code. - * - * @param contentPanel The panel that contains this description panel. - * @param constraints GridBagConstraints - insets, row, col, etc - * @param rowNum Row number for GridBagLayout - * @param mp MetaPref this description is for - * - * @return JLabel Description section - */ - private JLabel createDescriptionSection(JPanel contentPanel, GridBagConstraints constraints, int rowNum, MetaPref mp) - { - JLabel subDescription = createLabel(contentPanel,mp,0,0); - constraints.anchor = GridBagConstraints.FIRST_LINE_START; - constraints.gridx = 0; - constraints.gridy = rowNum; - constraints.gridwidth = 1; - constraints.insets = new Insets(TOP_GUI_INSET,LEFT_GUI_INSET,BOTTOM_GUI_INSET,0); // top,left,bottom,right - return subDescription; - } - - /** - * Creates a label for a preference. - * - * This is contained within {@link #createDescriptionSection(JPanel, GridBagConstraints, int, MetaPref)}. - * This contains {@link #wrapTooltip(MetaPref)}. - * - * This function includes xml-dependent code. - * - * @param panel JPanel this label will be associated with. - * @param mp MetaPref this label is for. - * @param row Row this label is in for GridBagLayout - * @param col Column this label is in for GridBagLayout - * - * @return JLabel with properties initialized to parameters. - */ - private JLabel createLabel(JPanel panel, MetaPref mp, int row, int col) - { - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.FIRST_LINE_START; - - JLabel label = new JLabel(); - String wrapText = "" + mp.getDescription() + ""; - label.setText(wrapText); - File prefsRoot = Assets.getAsset("preferences"); - File imgFile = new File(prefsRoot, "question1.png"); - ImageIcon imgIcon = new ImageIcon(imgFile.getAbsolutePath()); - label.setIcon(imgIcon); - - //nasty workaround because there is no API option to wrap tooltips - String formattedToolTip = wrapTooltip(mp); - - label.setToolTipText(formattedToolTip); - label.setHorizontalAlignment(SwingConstants.LEADING); - label.setHorizontalTextPosition(SwingConstants.RIGHT); - label.setVerticalAlignment(SwingConstants.TOP); - c.gridx = col; - c.gridy = row; - c.weightx = 0.5; - c.insets = new Insets(0,LEFT_GUI_INSET,0,0); // top,left,bottom,right - - panel.add(label, c); - - return label; - } - - /** - * This allows you to wrap the help tooltip text, because there is no - * way to normally do this. - * - * This is contained within {@link #createLabel(JPanel, MetaPref, int, int)}. - * - * @param mp MetaPref this tooltip is for. - * - * @return Tool tip wrapped via HTML. - */ - private String wrapTooltip(MetaPref mp) - { - String formattedToolTip = ""; - String hText = mp.getHelpText(); - if (hText != null && hText != "") - { - int tiplen = hText.length(); - int wrapAt = TOOLTIP_WRAP_WIDTH; - int nowAt = 0; - int breakAt = 0; - if (wrapAt > tiplen-1) - { - formattedToolTip = formattedToolTip.concat(hText.substring(nowAt, tiplen) + "
"); - } - else - { - do - { - nowAt = breakAt; - breakAt = hText.indexOf(" ", (nowAt+wrapAt)); - if (breakAt > tiplen-1) - { - formattedToolTip = formattedToolTip.concat(hText.substring(nowAt, tiplen) + "
"); - } - else if (breakAt > 0) - { - formattedToolTip = formattedToolTip.concat(hText.substring(nowAt, breakAt) + "
"); - } - else - { - formattedToolTip = formattedToolTip.concat(hText.substring(nowAt, tiplen) + "
"); - break; - } - } while(nowAt < tiplen-1); - } - } - formattedToolTip = formattedToolTip.concat(""); - return formattedToolTip; - } - - /** - * Creates a "change file" button for file chooser types - * and places it in the panel. - * - * @param mp metapref the button is associated with - * @param panel panel the button will be associated with - */ - private void createFileButton(MetaPref metaPref, JPanel panel) - { - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.LINE_START; - c.gridx = 0; - c.gridy = 0; - c.insets = new Insets(0,0,0,RIGHT_GUI_INSET); // top,left,bottom,right - - JButton jButton = new JButton(); - jButton.setText("Choose File"); - jButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - fileChooser.showOpenDialog(fileChooser.getParent()); - } - }); - registerComponent(metaPref, IDENTIFIER_FILE_CHOOSER, fileChooser); - panel.add(jButton,c); - } - - /** - * Creates a color chooser dialog for a color chooser metapref - * and places it on the panel. - * - * @param jPanel panel the dialog will be associated with - * @param mp metapref the chooser is being created for - */ - public static void setupColorChooser(JPanel jPanel, MetaPref mp) - { - colorChooserDialog = - JColorChooser.createDialog(jPanel, "Choose Stroke Color", true, - colorChooser, - new ActionListener() - { // ok listener - public void actionPerformed(ActionEvent e) - { - // nothing here - } - }, - new ActionListener() - { // cancel listener - public void actionPerformed(ActionEvent e) - { - // nothing here - } - } - ); - } - - /** - * Creates a color chooser button and places it on the panel. - * - * @param panel panel the button will be associated with - * @param mp MetaPref the button is for - */ - private void createColorChooser(JPanel panel, MetaPref mp) - { - setupColorChooser(panel,mp); - - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.LINE_START; - c.gridx = 0; - c.gridy = 0; - c.insets = new Insets(0,0,0,RIGHT_GUI_INSET); // top,left,bottom,right - - JButton jButton = new JButton(); - jButton.setText("Choose Color"); - jButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - colorChooserDialog.setVisible(true); - } - }); - panel.add(jButton,c); - registerComponent(mp, IDENTIFIER_COLOR_CHOOSER, colorChooser); - } - - /** - * This creates a radio button for a metapref that lists choices, rather - * than depending on default values. This is what you want for anything that is - * not: two options with the labels Yes and No. - * See also {@link #createYesNoBooleanRadio(MetaPref, JPanel)}. - * - * @param metaPref - * @param panel - */ - private void createChoicesBasedRadio(MetaPref metaPref, JPanel panel) - { - ArrayList> choices = metaPref.getChoices(); - if (choices != null) - { - ButtonGroup buttonGroup = new ButtonGroup(); - int rnum = 0; - for (Choice choice : choices) - { - final Object currentValue = metaPref.getDefaultValue(); - boolean isSelected = currentValue.equals(choice.getValue()); - createRadio(panel, metaPref, buttonGroup, isSelected, choice.getLabel(), choice.getName(), rnum, 0); - rnum++; - } - } - } - - /** - * This creates a radio button for a standard Yes/No boolean preference. - * See also {@link #createChoicesBasedRadio(MetaPref, JPanel)}. - * - * @param metaPref - * @param panel - */ - private void createYesNoBooleanRadio(MetaPrefBoolean metaPref, JPanel panel) - { - // Boolean currentValue = (Boolean) metaPref.getDefaultValue(); -- changed by andruid - Boolean currentValue = metaPref.usePrefBoolean().value(); - ArrayList> choices = metaPref.getChoices(); - ButtonGroup radioPair = new ButtonGroup(); - - if (choices != null) - {//This won't be used, since we make sure that this metapref has no choices while calling this function - ChoiceBoolean choice0 = (ChoiceBoolean) choices.get(0); - boolean isDefault = currentValue.equals(choice0.getValue()); - String name = isDefault ? IDENTIFIER_BOOLEAN_YES : IDENTIFIER_BOOLEAN_NO; - createRadio(panel, metaPref, radioPair, isDefault, choice0.getLabel(), name, 0, 0); - name = !isDefault ? IDENTIFIER_BOOLEAN_YES : IDENTIFIER_BOOLEAN_NO; - ChoiceBoolean choice1 = (ChoiceBoolean) choices.get(1); - createRadio(panel, metaPref, radioPair, isDefault, choice1.getLabel(), name, 1, 0); - } - else - { - boolean yesVal = currentValue; - boolean noVal = !currentValue; - createRadio(panel, metaPref, radioPair, yesVal, IDENTIFIER_BOOLEAN_YES, IDENTIFIER_BOOLEAN_YES, 0, 0); - createRadio(panel, metaPref, radioPair, noVal, IDENTIFIER_BOOLEAN_NO, IDENTIFIER_BOOLEAN_NO, 1, 0); - } - } - - public void windowActivated(WindowEvent e) - { - } - - public void windowClosed(WindowEvent e) - { - } - - /** - * Altered behavior: - * print that we are closing - * save our window location - */ - public void windowClosing(WindowEvent e) - { - System.err.print("window closing"); - saveLocation(); - } - - public void windowDeactivated(WindowEvent e) - { - } - - public void windowDeiconified(WindowEvent e) - { - } - - public void windowIconified(WindowEvent e) - { - } - - public void windowOpened(WindowEvent e) - { - } - - /** - * Creates a radio button. - * - * @param panel JPanel this button will be associated with. - * @param mp MetaPref this button is being created for. - * @param buttonGroup ButtonGroup this button is a member of. - * @param initialValue boolean; true=selected. false=not selected. - * @param label Text label for button - * @param name Name of button - * @param row Row this button is in for GridBagLayout - * @param col Column this button is in for GridBagLayout - * - * @return JRadioButton with properties initialized to parameters. - */ - protected JRadioButton createRadio(JPanel panel, MetaPref mp, ButtonGroup buttonGroup, boolean initialValue, String label, String name, int row, int col) - { - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.LINE_START; - - JRadioButton radioButton = new JRadioButton(); - - radioButton.setSelected(initialValue); - radioButton.setName(name); - radioButton.setText(label); - c.gridx = col; - c.gridy = row; - c.insets = new Insets(0,0,0,RIGHT_GUI_INSET); // top,left,bottom,right - - buttonGroup.add(radioButton); - panel.add(radioButton, c); - - // add metapref's component to array - Scope mpComponents = jCatComponentsMap.get(mp.getCategory()).get(mp.getID()); - if (mpComponents != null) - { - registerComponent(mp, name, radioButton); - } - - return radioButton; - } -} +package ecologylab.appframework.types.prefs.gui; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.io.File; +import java.util.ArrayList; +import java.util.LinkedHashMap; + +import javax.swing.ButtonGroup; +import javax.swing.ButtonModel; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JColorChooser; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JSlider; +import javax.swing.JSpinner; +import javax.swing.JTabbedPane; +import javax.swing.JTextField; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.ToolTipManager; + +import ecologylab.appframework.PropertiesAndDirectories; +import ecologylab.appframework.types.prefs.Choice; +import ecologylab.appframework.types.prefs.ChoiceBoolean; +import ecologylab.appframework.types.prefs.MetaPref; +import ecologylab.appframework.types.prefs.MetaPrefBoolean; +import ecologylab.appframework.types.prefs.MetaPrefFloat; +import ecologylab.appframework.types.prefs.MetaPrefInt; +import ecologylab.appframework.types.prefs.MetaPrefSet; +import ecologylab.appframework.types.prefs.Pref; +import ecologylab.appframework.types.prefs.PrefSet; +import ecologylab.collections.Scope; +import ecologylab.generic.Debug; +import ecologylab.generic.RestrictedFileSystemView; +import ecologylab.io.Assets; +import ecologylab.net.ParsedURL; + +/** + * Create the GUI for preference editing; also responsible for all + * actions associated with the GUI. + * + * @author Cae + * + */ +public class PrefsEditor +extends PrefEditorWidgets +implements WindowListener +{ + + /** + * The number of characters/columns at which the tooltips will try to wrap. + * Actual wrapping will be the nearest space AFTER this number. + */ + private static final int TOOLTIP_WRAP_WIDTH = 80; + /** + * A small inset for the top of an object in the GUI + */ + private static final int SMALL_TOP_GUI_INSET = 0; + /** + * The inset between the left side of the gui panel and the left + * side of the descriptions. + */ + private static final int LEFT_GUI_INSET = 20; + /** + * The inset between the top side of the gui panel and the object above it. + */ + private static final int TOP_GUI_INSET = 10; + /** + * The inset between the bottom of the gui section and the top of the + * next object. + */ + private static final int BOTTOM_GUI_INSET = 10; + + // base setup for gui + /** + * Base window for the GUI + */ + JFrame jFrame = null; + /** + * Cancel button for GUI + */ + JButton cancelButton = null; + /** + * Save button for GUI + */ + JButton saveButton = null; + /** + * Apply button for GUI + */ + JButton applyButton = null; + /** + * Revert button for GUI + */ + JButton revertButton = null; + /** + * Tabbed pane within content pane within base window for GUI + */ + JTabbedPane jTabbedPane = null; + + /** + * Whether we're called this standalone or not + */ + boolean isStandalone; + + /** + * Start location on the screen for the gui + */ + static Point startLocation = new Point(100,100); + + /** + * Color picker; static so we only have one. + */ + static JColorChooser colorChooser = new JColorChooser(); + static JDialog colorChooserDialog; + + /** + * File chooser; static so we only have one. + * Instantiation is performed within a static block for error handling. + * If the standard JFileChooser cannot open due to an exception, as described in the Bug listing + */ + static JFileChooser fileChooser; + + static + { + try + { + fileChooser = new JFileChooser(PropertiesAndDirectories.desktopDir()); + } + catch(Exception e) + { + Debug.println("Using RestrictedFileSystemView for PrefsEditor JFileChooser"); + fileChooser = new JFileChooser(PropertiesAndDirectories.desktopDir(), new RestrictedFileSystemView()); + } + } + + /** + * File dialog; static so we only have one. + */ + static JDialog fileChooserDialog; + + /** + * The base function that you call to construct the prefs editor GUI. + * This requires that the MetaPrefSet and PrefSet be instantiated and populated + * prior to call. This function creates the entire GUI and handles all actions + * for it. + * + * @param metaPrefSet Set of MetaPrefs + * @param prefSet Set of Prefs + * @param savePrefsPURL ParsedURL to save prefs.xml to + * @param isStandalone Whether or not we're calling this standalone + */ + public PrefsEditor(MetaPrefSet metaPrefSet, PrefSet prefSet, ParsedURL savePrefsPURL, final boolean createJFrame, final boolean isStandalone) + { + super (metaPrefSet, prefSet, savePrefsPURL); + + this.isStandalone = isStandalone; + + setupContainer(createJFrame, isStandalone); + } + + /** + * Calls createJFrame + * @see #createJFrame() + * @return Base window (JFrame) for the GUI + */ + public Container setupContainer(final boolean createJFrame, final boolean isStandalone) + { + Container result = createContainer(createJFrame); + if (createJFrame) + { + jFrame.addWindowListener(new WindowAdapter() + { + @Override public void windowClosing(WindowEvent e) + { + closeWindow(); + } + }); + jFrame.setVisible(true); + } + return result; + } + + /** + * Create the base window for the GUI. + * + * This contains {@link #createJContentPane()}. + * + * This is a static part of the GUI. + * + * @return Base window (JFrame) for the GUI + */ + // static bits of gui + private Container createContainer(boolean createJFrame) + { + Container result = null; + if (createJFrame) + { + if (jFrame == null) + { + jFrame = new JFrame(); + jFrame.setContentPane(createJContentPane()); + jFrame.addWindowListener(this); + String title = metaPrefSet.getTitle(); + if (title == null) + title = "Preferences Editor"; + jFrame.setTitle(title); + } + result = jFrame; + } + else + { + result = createJContentPane(); + } + setSize(result); + return result; + } + + private void setSize(Container jContainer) + { + int width = metaPrefSet.getWidth(); + if (width == 0) + width = 603; + int height = metaPrefSet.getHeight(); + if (height == 0) + height = 532; + jContainer.setPreferredSize(new Dimension(width, height)); + jContainer.setSize(new Dimension(width, height)); + } + + /** + * Function to close the window + */ + private void closeWindow() + { + if (jFrame != null) + { + jFrame.setVisible(false); + jFrame.dispose(); + } + if (PrefsEditor.this.isStandalone) + System.exit(0); + } + + /** + * Function to close the window + */ + private void saveLocation() + { + startLocation = jFrame.getLocation(); + } + + /** + * Create the content pane within the base window for the GUI. + * + * This is contained within {@link #createJFrame()}. + * This contains {@link #createApplyButton()}, {@link #createCancelButton()}, + * and {@link #createRevertButton()}, {@link #createSaveButton()}, + * and {@link #createJTabbedPane()}. + * + * This is a static part of the GUI. + * + * @return Content pane (JPanel) within the base window for the GUI + */ + private JPanel createJContentPane() + { + if (jContentPane == null) + { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(createJTabbedPane(), null); + jContentPane.add(createCancelButton(), null); + jContentPane.add(createSaveButton(), null); + jContentPane.add(createApplyButton(), null); + jContentPane.add(createRevertButton(), null); + } + return jContentPane; + } + + /** + * Create the cancel button for the GUI. This button closes + * the window without saving the prefs. + * This is contained within {@link #createJContentPane()}. + * This is a static part of the GUI. + * + * @return Cancel button (JButton) for GUI + */ + private JButton createCancelButton() + { + if (cancelButton == null) + { + cancelButton = new JButton(); + cancelButton.setBounds(new Rectangle(482, 435, 89, 35)); + cancelButton.setText("Cancel"); + cancelButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + saveLocation(); + closeWindow(); + } + }); + } + return cancelButton; + } + + /** + * Create the save button for the GUI. This button saves + * prefs and closes the window. + * + * This is contained within {@link #createJContentPane()}. + * This contains {@link #actionSavePreferences()}. + * + * This is a static part of the GUI. + * + * @return Save button (JButton) for GUI + */ + JButton createSaveButton() + { + if (saveButton == null) + { + saveButton = new JButton(); + saveButton.setBounds(new Rectangle(379, 435, 89, 35)); + saveButton.setText("Save"); + saveButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + saveLocation(); + actionSavePreferences(); + closeWindow(); + } + }); + } + return saveButton; + } + + /** + * Create the apply button for the GUI. This saves the prefs + * and doesn't close the window. + * + * This is contained within {@link #createJContentPane()}. + * This contains {@link #actionSavePreferences()}. + * + * This is a static part of the GUI. + * + * @return Apply button (JButton) for GUI + */ + JButton createApplyButton() + { + if (applyButton == null) + { + applyButton = new JButton(); + applyButton.setBounds(new Rectangle(276, 435, 89, 35)); + applyButton.setText("Apply"); + applyButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + actionSavePreferences(); + } + }); + } + return applyButton; + } + + /** + * Create the revert button for the GUI. This reverts the + * prefs to their default values when pressed. + * + * This is contained within {@link #createJContentPane()}. + * This contains {@link #actionRevertPreferencesToDefault()}. + * + * This is a static part of the GUI. + * + * @return Revert button (JButton) for GUI + */ + private JButton createRevertButton() + { + if (revertButton == null) + { + revertButton = new JButton(); + revertButton.setBounds(new Rectangle(15, 435, 137, 35)); + revertButton.setText("Revert to Default"); + revertButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + actionRevertPreferencesToDefault(); + } + }); + } + return revertButton; + } + // end of static bits of gui + + // bits of gui that are all or part auto-generated + /** + * Create the tabbed pane within the main frame within the main + * window of the GUI. This pane contains the content panes which define + * the actual tabs of the GUI. + * + * This is contained within {@link #createJContentPane()}. + * This contains {@link #getTabbedBodyFrame(String, JScrollPane)}. + * + * This function includes xml-dependent code. + * + * @return Tabbed pane within which the tabs for the GUI are defined + */ + private JTabbedPane createJTabbedPane() + { + if (jTabbedPane == null) + { + jTabbedPane = new JTabbedPane(); + jTabbedPane.setName("jTabbedPane"); + jTabbedPane.setBounds(new Rectangle(0, 0, 595, 416)); + + String[] orderedTabNames = new String[metaPrefSet.getNumberOfTabs()]; + metaPrefSet.getOrderedTabNames(orderedTabNames); + for (String cat : orderedTabNames) + { + JScrollPane scrollPane = new JScrollPane(); + scrollPane.setSize(new Dimension(jTabbedPane.getWidth(),jTabbedPane.getHeight())); + scrollPane.setComponentOrientation(java.awt.ComponentOrientation.LEFT_TO_RIGHT); + scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setName(cat); + scrollPane.setViewportView(getTabbedBodyFrame(cat,scrollPane)); + jTabbedPane.addTab(cat, null, scrollPane, null); + + // add category to components map + LinkedHashMap> catHash = jCatComponentsMap.get(cat); + if (catHash == null) + { + catHash = new LinkedHashMap>(); + jCatComponentsMap.put(cat, catHash); + //System.err.print("Adding: " + cat + '\n'); + } + } + } + return jTabbedPane; + } + + /** + * The actual tab for a category within the GUI. + * + * This is contained within {@link #createJTabbedPane()} + * This contains {@link #createDescriptionSection(JPanel, GridBagConstraints, int, MetaPref)}, + * and {@link #createWidgetFromMetaPref(GridBagConstraints, MetaPref, int)}, + * and {@link #createSeparator(GridBagConstraints, int)}. + * + * This function includes xml-dependent code. + * + * @param category Name of category + * @param scrollPane The pane that scrolls within this panel + * + * @return Tab for a category within the GUI + */ + @SuppressWarnings("serial") + private JPanel getTabbedBodyFrame(String category, JScrollPane scrollPane) + { + JPanel contentPanel = new JPanel() + { + private boolean firstTime = true; + @Override public void paintComponent(Graphics g) + { + if (firstTime) + { + firstTime = false; + int numberOfEntries = this.getComponentCount(); + for (int i=0; i < numberOfEntries; i+=3) + { + // TODO: this only works because we alternate adding JLabels and JPanels and JSeparators + if ((this.getComponent(i) instanceof JLabel) && (this.getComponent(i+1) instanceof JPanel) && (this.getComponent(i+2) instanceof JSeparator)) + { + JLabel desc = (JLabel)this.getComponent(i); + JPanel val = (JPanel)this.getComponent(i+1); + JSeparator sep = (JSeparator)this.getComponent(i+2); + + FontMetrics fm = desc.getFontMetrics(desc.getFont()); + int actualWidth = (this.getWidth()-val.getWidth())-LEFT_GUI_INSET; + int stringWidth = SwingUtilities.computeStringWidth(fm, desc.getText()); + + desc.setPreferredSize(new Dimension(actualWidth,((stringWidth/actualWidth)+1)*fm.getHeight())); + sep.setPreferredSize(new Dimension(this.getWidth()-(LEFT_GUI_INSET*2),3)); + if (i+3 == numberOfEntries) + { + // make last separator invisible + sep.setVisible(false); + } + } + } + } + super.paintComponent(g); + } + }; + + // make tooltips display quickly + ToolTipManager.sharedInstance().setInitialDelay(10); + contentPanel.setLayout(new GridBagLayout()); + contentPanel.setMaximumSize(new Dimension(scrollPane.getWidth(),Integer.MAX_VALUE)); + GridBagConstraints constraints = new GridBagConstraints(); + constraints.weightx = 0.1; + int rowNum = 0; + for (MetaPref metaPref : metaPrefSet.getMetaPrefListByCategory(category)) + { + // add metapref to components map + //System.err.print(category + '\n' + metaPref.getID() + '\n'); + LinkedHashMap> catHash = jCatComponentsMap.get(category); + if (catHash == null) + { + catHash = new LinkedHashMap>(); + jCatComponentsMap.put(category, catHash); + } + Scope mpComponentRegistry = catHash.get(metaPref.getID()); + if (mpComponentRegistry == null) + { + mpComponentRegistry = new Scope(); + catHash.put(metaPref.getID(), mpComponentRegistry); + } + + JLabel subDescription = createDescriptionSection(contentPanel, constraints, rowNum, metaPref); + JPanel subValue = createWidgetFromMetaPref(constraints, metaPref, rowNum); + + subValue.setMaximumSize(new Dimension(scrollPane.getWidth()/2,100)); + subDescription.setMaximumSize(new Dimension(scrollPane.getWidth()/2,50)); + + // we have to do this in order for our redraw code to work properly. + subDescription.setPreferredSize(new Dimension(1,1)); + + //add these suckers to the contentpanel. + constraints.anchor = GridBagConstraints.FIRST_LINE_START; + contentPanel.add(subDescription, constraints); + if (subValue != null) + { + constraints.anchor = GridBagConstraints.FIRST_LINE_END; + contentPanel.add(subValue, constraints); + } + JSeparator separator = createSeparator(constraints, rowNum); + constraints.anchor = GridBagConstraints.NORTH; + contentPanel.add(separator,constraints); + rowNum++; + } + + return contentPanel; + } + + /** + * Create the UI component (aka widget) that enables the user to manipulate the value of the preference. + * This is contained within {@link #getTabbedBodyFrame(String, JScrollPane)}. + * This function includes xml-dependent code. + * + * @param constraints GridBagConstraints - insets, row, col, etc + * @param metaPref Description of what widget type to use, default values, ... + * @param rowNum Row number for GridBagLayout + * + * @return JLabel Value section + */ + private JPanel createWidgetFromMetaPref(GridBagConstraints constraints, MetaPref metaPref, int rownum) + { + JPanel panel = new JPanel(); + panel.setName(metaPref.getID()); + panel.setLayout(new GridBagLayout()); + + if (metaPref.widgetIsTextField()) + { + createTextField(panel, metaPref); + } + else if (metaPref.widgetIsRadio()) + { + if (metaPref instanceof MetaPrefBoolean && !metaPref.hasChoices()) + { + createYesNoBooleanRadio((MetaPrefBoolean) metaPref, panel); + } + else + { + createChoicesBasedRadio(metaPref, panel); + } + } + else if (metaPref.widgetIsDropDown()) + { + createDropDown(panel, metaPref); + } + else if (metaPref.widgetIsCheckBox()) + { + createCheckBox(panel, metaPref); + } + else if (metaPref.widgetIsSlider()) + { + if (metaPref instanceof MetaPrefInt) + { + createSlider(panel, metaPref, IDENTIFIER_SLIDER, false, 0); + } + else if (metaPref instanceof MetaPrefFloat) + { + createSlider(panel, metaPref, IDENTIFIER_SLIDER, true, FLOAT_SLIDER_MODIFIER); + } + } + else if (metaPref.widgetIsSpinner()) + { + createSpinner(panel, metaPref); + } + else if (metaPref.widgetIsColorChooser()) + { + createColorChooser(panel, metaPref); + } + else if (metaPref.widgetIsFileChooser()) + { + createFileButton(metaPref, panel); + } + + panel.setVisible(true); + + if (panel != null) + { + constraints.gridx = 1; + constraints.gridy = rownum; + constraints.gridwidth = 1; + constraints.insets = new Insets(TOP_GUI_INSET,LEFT_GUI_INSET,BOTTOM_GUI_INSET,0); // top,left,bottom,right + // if we have a prefs value, override it now + if (Pref.hasPref(metaPref.getID())) + { + setWidgetToPrefValue(metaPref, Pref.lookupPref(metaPref.getID())); + } + } + return panel; + } + + /** + * Set the metapref's widget in the prefs editor to the value in + * the prefs xml file. + * + * @param mp metapref + * @param pref pref to set metapref's widget to + */ + private void setWidgetToPrefValue(MetaPref mp, Pref pref) + { + if (mp.widgetIsTextField()) + { + JTextField textField = (JTextField)lookupComponent(mp, mp.getID()+IDENTIFIER_TEXT_FIELD); + textField.setText(pref.value().toString()); + } + else if (mp.widgetIsRadio()) + { + if (mp instanceof MetaPrefBoolean && !mp.hasChoices()) + { + boolean prefValue = (Boolean)pref.value(); + if (prefValue) + { + JRadioButton yesButton = (JRadioButton)lookupComponent(mp, mp.getID()+IDENTIFIER_BOOLEAN_YES); + ButtonModel yesModel = yesButton.getModel(); + yesModel.setSelected(true); + } + else + { + JRadioButton noButton = (JRadioButton)lookupComponent(mp, mp.getID()+IDENTIFIER_BOOLEAN_NO); + ButtonModel noModel = noButton.getModel(); + noModel.setSelected(true); + } + } + else + { + // registered name + String regName = mp.getID() + mp.getChoiceNameByValue(pref.value().toString()); + JRadioButton defaultButton = (JRadioButton) lookupComponent(mp,regName); + ButtonModel buttonModel = defaultButton.getModel(); + buttonModel.setSelected(true); + } + } + else if (mp.widgetIsDropDown()) + { + JComboBox comboBox = (JComboBox)lookupComponent(mp, mp.getID() + IDENTIFIER_DROPDOWN); + comboBox.setSelectedIndex(mp.getIndexByValue(pref.value().toString())); + } + else if (mp.widgetIsCheckBox()) + { + JCheckBox checkBox = (JCheckBox)lookupComponent(mp, mp.getID() + IDENTIFIER_CHECK_BOX); + checkBox.setSelected((Boolean)pref.value()); + } + else if (mp.widgetIsSlider()) + { + if (mp instanceof MetaPrefInt) + { + Integer prefValue = (Integer)pref.value(); + JSlider jSlider = (JSlider)lookupComponent(mp,mp.getID()+IDENTIFIER_SLIDER); + jSlider.setValue(prefValue); + } + else if (mp instanceof MetaPrefFloat) + { + Float prefValue = (Float)pref.value(); + JSlider jSlider = (JSlider)lookupComponent(mp,mp.getID()+IDENTIFIER_SLIDER); + jSlider.setValue((int)(prefValue*FLOAT_SLIDER_MODIFIER)); + } + } + else if (mp.widgetIsSpinner()) + { + JSpinner jSpinner = (JSpinner)lookupComponent(mp,mp.getID()+IDENTIFIER_SPINNER); + jSpinner.setValue(pref.value()); + } + else if (mp.widgetIsColorChooser()) + { + Color prefValue = (Color)pref.value(); + JColorChooser colorChooser = (JColorChooser)lookupComponent(mp,mp.getID()+IDENTIFIER_COLOR_CHOOSER); + if (colorChooser != null) + { + colorChooser.setColor(prefValue); + } + } + else if (mp.widgetIsFileChooser()) + { + JFileChooser fileChooser = (JFileChooser)lookupComponent(mp,mp.getID()+IDENTIFIER_FILE_CHOOSER); + fileChooser.setSelectedFile((File)pref.value()); + } + } + + /** + * Revert the metapref's widget to the default value for it, defined + * in the metaprefs xml file. + * + * @param mp metapref to revert + */ + private void revertToDefault(MetaPref mp) + { + if (mp.widgetIsTextField()) + { + JTextField textField = (JTextField)lookupComponent(mp, mp.getID()+IDENTIFIER_TEXT_FIELD); + textField.setText(mp.getDefaultValue().toString()); + } + else if (mp.widgetIsRadio()) + { + if (mp instanceof MetaPrefBoolean && !mp.hasChoices()) + { + // get button + JRadioButton yesButton = (JRadioButton)lookupComponent(mp, mp.getID()+IDENTIFIER_BOOLEAN_YES); + ButtonModel yesModel = yesButton.getModel(); + boolean yesVal = (Boolean)mp.getDefaultValue(); + + if (yesVal) + { + yesModel.setSelected(true); + } + else + { + JRadioButton noButton = (JRadioButton)lookupComponent(mp, mp.getID()+IDENTIFIER_BOOLEAN_NO); + ButtonModel noModel = noButton.getModel(); + noModel.setSelected(true); + } + } + else + { + String regName = mp.getID() + mp.getChoiceNameByValue(mp.getDefaultValue().toString()); + //println("we think the name is: " + regName); + JRadioButton defaultButton = (JRadioButton)lookupComponent(mp,regName); + ButtonModel buttonModel = defaultButton.getModel(); + buttonModel.setSelected(true); + } + } + else if (mp.widgetIsDropDown()) + { + JComboBox comboBox = (JComboBox)lookupComponent(mp,mp.getID()+IDENTIFIER_DROPDOWN); + comboBox.setSelectedIndex(mp.getIndexByValue(mp.getDefaultValue().toString())); + } + else if (mp.widgetIsCheckBox()) + { + JCheckBox checkBox = (JCheckBox)lookupComponent(mp, mp.getID() + IDENTIFIER_CHECK_BOX); + checkBox.setSelected((Boolean)mp.getDefaultValue()); + } + else if (mp.widgetIsSlider()) + { + if (mp instanceof MetaPrefInt) + { + JSlider jSlider = (JSlider)lookupComponent(mp,mp.getID()+IDENTIFIER_SLIDER); + jSlider.setValue((Integer)mp.getDefaultValue()); + } + else if (mp instanceof MetaPrefFloat) + { + int alteredDefault = (int)((Float)mp.getDefaultValue()*FLOAT_SLIDER_MODIFIER); + JSlider jSlider = (JSlider)lookupComponent(mp,mp.getID()+IDENTIFIER_SLIDER); + jSlider.setValue(alteredDefault); + } + } + else if (mp.widgetIsSpinner()) + { + JSpinner jSpinner = (JSpinner)lookupComponent(mp,mp.getID()+IDENTIFIER_SPINNER); + jSpinner.setValue(mp.getDefaultValue()); + } + else if (mp.widgetIsColorChooser()) + { + JColorChooser colorChooser = (JColorChooser)lookupComponent(mp,mp.getID()+IDENTIFIER_COLOR_CHOOSER); + colorChooser.setColor((Color)mp.getDefaultValue()); + } + else if (mp.widgetIsFileChooser()) + { + JFileChooser fileChooser = (JFileChooser)lookupComponent(mp,mp.getID()+IDENTIFIER_FILE_CHOOSER); + fileChooser.setSelectedFile((File)mp.getDefaultValue()); + } + } + + /** + * The function that actually performs the revert-to-default actions + * is in the MetaPrefType classes. + */ + private void actionRevertPreferencesToDefault() + { + for (String cat : metaPrefSet.getCategories()) + { + for (MetaPref mp : metaPrefSet.getMetaPrefListByCategory(cat)) + { + revertToDefault(mp); + } + } + } + // end of gui actions for buttons + + /** + * Creates a separator to go between two preferences in the GUI. + * This is contained within {@link #getTabbedBodyFrame(String, JScrollPane)}. + * This function includes xml-dependent code. + * + * @param constraints GridBagConstraints - insets, row, col, etc + * @param rowNum Row number for GridBagLayout + * + * @return JSeparator for tab frame in GUI + */ + private JSeparator createSeparator(GridBagConstraints constraints, int rowNum) + { + JSeparator separator = new JSeparator(SwingConstants.HORIZONTAL); + constraints.gridx = 0; + constraints.gridy = rowNum + 1; + constraints.gridwidth = 2; + constraints.insets = new Insets(SMALL_TOP_GUI_INSET,0,0,0); + return separator; + } + + /** + * Create the description section for a preference. + * + * This is contained within {@link #getTabbedBodyFrame(String, JScrollPane)}. + * This contains {@link #createLabel(JPanel, MetaPref, int, int)}. + * + * This function includes xml-dependent code. + * + * @param contentPanel The panel that contains this description panel. + * @param constraints GridBagConstraints - insets, row, col, etc + * @param rowNum Row number for GridBagLayout + * @param mp MetaPref this description is for + * + * @return JLabel Description section + */ + private JLabel createDescriptionSection(JPanel contentPanel, GridBagConstraints constraints, int rowNum, MetaPref mp) + { + JLabel subDescription = createLabel(contentPanel,mp,0,0); + constraints.anchor = GridBagConstraints.FIRST_LINE_START; + constraints.gridx = 0; + constraints.gridy = rowNum; + constraints.gridwidth = 1; + constraints.insets = new Insets(TOP_GUI_INSET,LEFT_GUI_INSET,BOTTOM_GUI_INSET,0); // top,left,bottom,right + return subDescription; + } + + /** + * Creates a label for a preference. + * + * This is contained within {@link #createDescriptionSection(JPanel, GridBagConstraints, int, MetaPref)}. + * This contains {@link #wrapTooltip(MetaPref)}. + * + * This function includes xml-dependent code. + * + * @param panel JPanel this label will be associated with. + * @param mp MetaPref this label is for. + * @param row Row this label is in for GridBagLayout + * @param col Column this label is in for GridBagLayout + * + * @return JLabel with properties initialized to parameters. + */ + private JLabel createLabel(JPanel panel, MetaPref mp, int row, int col) + { + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.FIRST_LINE_START; + + JLabel label = new JLabel(); + String wrapText = "" + mp.getDescription() + ""; + label.setText(wrapText); + File prefsRoot = Assets.getAsset("preferences"); + File imgFile = new File(prefsRoot, "question1.png"); + ImageIcon imgIcon = new ImageIcon(imgFile.getAbsolutePath()); + label.setIcon(imgIcon); + + //nasty workaround because there is no API option to wrap tooltips + String formattedToolTip = wrapTooltip(mp); + + label.setToolTipText(formattedToolTip); + label.setHorizontalAlignment(SwingConstants.LEADING); + label.setHorizontalTextPosition(SwingConstants.RIGHT); + label.setVerticalAlignment(SwingConstants.TOP); + c.gridx = col; + c.gridy = row; + c.weightx = 0.5; + c.insets = new Insets(0,LEFT_GUI_INSET,0,0); // top,left,bottom,right + + panel.add(label, c); + + return label; + } + + /** + * This allows you to wrap the help tooltip text, because there is no + * way to normally do this. + * + * This is contained within {@link #createLabel(JPanel, MetaPref, int, int)}. + * + * @param mp MetaPref this tooltip is for. + * + * @return Tool tip wrapped via HTML. + */ + private String wrapTooltip(MetaPref mp) + { + String formattedToolTip = ""; + String hText = mp.getHelpText(); + if (hText != null && hText != "") + { + int tiplen = hText.length(); + int wrapAt = TOOLTIP_WRAP_WIDTH; + int nowAt = 0; + int breakAt = 0; + if (wrapAt > tiplen-1) + { + formattedToolTip = formattedToolTip.concat(hText.substring(nowAt, tiplen) + "
"); + } + else + { + do + { + nowAt = breakAt; + breakAt = hText.indexOf(" ", (nowAt+wrapAt)); + if (breakAt > tiplen-1) + { + formattedToolTip = formattedToolTip.concat(hText.substring(nowAt, tiplen) + "
"); + } + else if (breakAt > 0) + { + formattedToolTip = formattedToolTip.concat(hText.substring(nowAt, breakAt) + "
"); + } + else + { + formattedToolTip = formattedToolTip.concat(hText.substring(nowAt, tiplen) + "
"); + break; + } + } while(nowAt < tiplen-1); + } + } + formattedToolTip = formattedToolTip.concat(""); + return formattedToolTip; + } + + /** + * Creates a "change file" button for file chooser types + * and places it in the panel. + * + * @param mp metapref the button is associated with + * @param panel panel the button will be associated with + */ + private void createFileButton(MetaPref metaPref, JPanel panel) + { + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.LINE_START; + c.gridx = 0; + c.gridy = 0; + c.insets = new Insets(0,0,0,RIGHT_GUI_INSET); // top,left,bottom,right + + JButton jButton = new JButton(); + jButton.setText("Choose File"); + jButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + fileChooser.showOpenDialog(fileChooser.getParent()); + } + }); + registerComponent(metaPref, IDENTIFIER_FILE_CHOOSER, fileChooser); + panel.add(jButton,c); + } + + /** + * Creates a color chooser dialog for a color chooser metapref + * and places it on the panel. + * + * @param jPanel panel the dialog will be associated with + * @param mp metapref the chooser is being created for + */ + public static void setupColorChooser(JPanel jPanel, MetaPref mp) + { + colorChooserDialog = + JColorChooser.createDialog(jPanel, "Choose Stroke Color", true, + colorChooser, + new ActionListener() + { // ok listener + public void actionPerformed(ActionEvent e) + { + // nothing here + } + }, + new ActionListener() + { // cancel listener + public void actionPerformed(ActionEvent e) + { + // nothing here + } + } + ); + } + + /** + * Creates a color chooser button and places it on the panel. + * + * @param panel panel the button will be associated with + * @param mp MetaPref the button is for + */ + private void createColorChooser(JPanel panel, MetaPref mp) + { + setupColorChooser(panel,mp); + + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.LINE_START; + c.gridx = 0; + c.gridy = 0; + c.insets = new Insets(0,0,0,RIGHT_GUI_INSET); // top,left,bottom,right + + JButton jButton = new JButton(); + jButton.setText("Choose Color"); + jButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + colorChooserDialog.setVisible(true); + } + }); + panel.add(jButton,c); + registerComponent(mp, IDENTIFIER_COLOR_CHOOSER, colorChooser); + } + + /** + * This creates a radio button for a metapref that lists choices, rather + * than depending on default values. This is what you want for anything that is + * not: two options with the labels Yes and No. + * See also {@link #createYesNoBooleanRadio(MetaPref, JPanel)}. + * + * @param metaPref + * @param panel + */ + private void createChoicesBasedRadio(MetaPref metaPref, JPanel panel) + { + ArrayList> choices = metaPref.getChoices(); + if (choices != null) + { + ButtonGroup buttonGroup = new ButtonGroup(); + int rnum = 0; + for (Choice choice : choices) + { + final Object currentValue = metaPref.getDefaultValue(); + boolean isSelected = currentValue.equals(choice.getValue()); + createRadio(panel, metaPref, buttonGroup, isSelected, choice.getLabel(), choice.getName(), rnum, 0); + rnum++; + } + } + } + + /** + * This creates a radio button for a standard Yes/No boolean preference. + * See also {@link #createChoicesBasedRadio(MetaPref, JPanel)}. + * + * @param metaPref + * @param panel + */ + private void createYesNoBooleanRadio(MetaPrefBoolean metaPref, JPanel panel) + { + // Boolean currentValue = (Boolean) metaPref.getDefaultValue(); -- changed by andruid + Boolean currentValue = metaPref.usePrefBoolean().value(); + ArrayList> choices = metaPref.getChoices(); + ButtonGroup radioPair = new ButtonGroup(); + + if (choices != null) + {//This won't be used, since we make sure that this metapref has no choices while calling this function + ChoiceBoolean choice0 = (ChoiceBoolean) choices.get(0); + boolean isDefault = currentValue.equals(choice0.getValue()); + String name = isDefault ? IDENTIFIER_BOOLEAN_YES : IDENTIFIER_BOOLEAN_NO; + createRadio(panel, metaPref, radioPair, isDefault, choice0.getLabel(), name, 0, 0); + name = !isDefault ? IDENTIFIER_BOOLEAN_YES : IDENTIFIER_BOOLEAN_NO; + ChoiceBoolean choice1 = (ChoiceBoolean) choices.get(1); + createRadio(panel, metaPref, radioPair, isDefault, choice1.getLabel(), name, 1, 0); + } + else + { + boolean yesVal = currentValue; + boolean noVal = !currentValue; + createRadio(panel, metaPref, radioPair, yesVal, IDENTIFIER_BOOLEAN_YES, IDENTIFIER_BOOLEAN_YES, 0, 0); + createRadio(panel, metaPref, radioPair, noVal, IDENTIFIER_BOOLEAN_NO, IDENTIFIER_BOOLEAN_NO, 1, 0); + } + } + + public void windowActivated(WindowEvent e) + { + } + + public void windowClosed(WindowEvent e) + { + } + + /** + * Altered behavior: + * print that we are closing + * save our window location + */ + public void windowClosing(WindowEvent e) + { + System.err.print("window closing"); + saveLocation(); + } + + public void windowDeactivated(WindowEvent e) + { + } + + public void windowDeiconified(WindowEvent e) + { + } + + public void windowIconified(WindowEvent e) + { + } + + public void windowOpened(WindowEvent e) + { + } + + /** + * Creates a radio button. + * + * @param panel JPanel this button will be associated with. + * @param mp MetaPref this button is being created for. + * @param buttonGroup ButtonGroup this button is a member of. + * @param initialValue boolean; true=selected. false=not selected. + * @param label Text label for button + * @param name Name of button + * @param row Row this button is in for GridBagLayout + * @param col Column this button is in for GridBagLayout + * + * @return JRadioButton with properties initialized to parameters. + */ + protected JRadioButton createRadio(JPanel panel, MetaPref mp, ButtonGroup buttonGroup, boolean initialValue, String label, String name, int row, int col) + { + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.LINE_START; + + JRadioButton radioButton = new JRadioButton(); + + radioButton.setSelected(initialValue); + radioButton.setName(name); + radioButton.setText(label); + c.gridx = col; + c.gridy = row; + c.insets = new Insets(0,0,0,RIGHT_GUI_INSET); // top,left,bottom,right + + buttonGroup.add(radioButton); + panel.add(radioButton, c); + + // add metapref's component to array + Scope mpComponents = jCatComponentsMap.get(mp.getCategory()).get(mp.getID()); + if (mpComponents != null) + { + registerComponent(mp, name, radioButton); + } + + return radioButton; + } +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/gui/package.html b/simplSunSpecifics/src/ecologylab/appframework/types/prefs/gui/package.html similarity index 96% rename from simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/gui/package.html rename to simplSunSpecifics/src/ecologylab/appframework/types/prefs/gui/package.html index fe7c0d5b..d8522271 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/appframework/types/prefs/gui/package.html +++ b/simplSunSpecifics/src/ecologylab/appframework/types/prefs/gui/package.html @@ -1,3 +1,3 @@ - -GUI elements for manipulating preferences within applications. - + +GUI elements for manipulating preferences within applications. + diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/image/AlphaGradientRendering.java b/simplSunSpecifics/src/ecologylab/image/AlphaGradientRendering.java similarity index 96% rename from simplPlatformSpecifics/Sun/src/ecologylab/image/AlphaGradientRendering.java rename to simplSunSpecifics/src/ecologylab/image/AlphaGradientRendering.java index 68b4e135..dca3d9b8 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/image/AlphaGradientRendering.java +++ b/simplSunSpecifics/src/ecologylab/image/AlphaGradientRendering.java @@ -1,188 +1,188 @@ -package ecologylab.image; - -import java.awt.Graphics; -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.DataBuffer; -import java.awt.image.SampleModel; -import java.awt.image.SinglePixelPackedSampleModel; - -import ecologylab.generic.Colors; -import ecologylab.generic.ImageTools; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -/** - * @author andruid - * - * To change this generated comment edit the template variable "typecomment": - * Window>Preferences>Java>Templates. - * To enable and disable the creation of type comments go to - * Window>Preferences>Java>Code Generation. - */ -@simpl_inherit -public class AlphaGradientRendering extends Rendering -{ - @simpl_scalar - float radius; - - @simpl_scalar - int minAlpha; - - int minAlphaInt; - - public AlphaGradientRendering() - { - - } - -/** - * Constructor for AlphaGradientRendering. - * @param previousRendering - * @param active - */ - public AlphaGradientRendering(Rendering previousRendering, boolean active) - { - this(previousRendering, active, 0, ((int) (((float)0 / 255.0f) * (float) Colors.R)) & Colors.R ); - } - - public AlphaGradientRendering(Rendering previousRendering, boolean active, int radius, int minAlpha) - { - super(previousRendering, active); - this.radius = radius; - this.minAlpha = minAlpha; - minAlphaInt = 0; - } - - public void compute(int radius, int minAlpha) - { - this.radius = radius; - this.minAlpha = minAlpha; - doCompute(true, previousRendering); - isActive = true; - } - public void compute0(int[] inPixels, int[] outPixels) - { - fill(outPixels, G + B); - } - public void compute(Rendering inputRendering, Rendering outputRendering) - { - // cant use straight copy, because JPG images are read with 3 bands. - // if they dont get scaled, the source pixels may not have alpha set! - //System.arraycopy(inPixels, 0, outPixels, 0, inPixels.length); - - // let the graphics context do the copy, so it can smartly fix alpha - ImageTools.copyImage(inputRendering.bufferedImage, outputRendering.bufferedImage); - - int[] outPixels = outputRendering.pixels; - - // work in red space, to avoid signed arithmetic problems; - // shift up later - - // gradientMagnitude is the full delta of alpha, across the - // gradient area. - int gradientMagnitude = R - minAlpha; - int pixelIndex = 0; - int beyondRight = (int)(width - radius); // x >= places in gradient - int beyondBottom = (int)(height - radius);// y >= places in gradient - // debug("radius="+radius+ ", minAlpha="+Integer.toHexString(minAlpha) + - // ", gradientMagnitude="+hex(gradientMagnitude) + - // "\t"+width+"x"+height+"\n"); - for (int j=0; j= beyondBottom) - yFactor = height - j - 1; - for (int i=0; i= beyondRight) - xFactor = width - i - 1; - if (xFactor < gradientFactor) - gradientFactor = xFactor; - - if (gradientFactor < radius) - { - double gradientChange = ((float) gradientFactor / radius) * gradientMagnitude ; - int thisGradient = // shift to compensate for sign avoidance - ((int) gradientChange + minAlpha)<< 8; - - // !!! already blt-ed them all over - // int thisPixel = outPixels[pixelIndex]; - //int srcPixel = inPixels[pixelIndex]; - // note: input pixels have been copied to output pixels already! - int srcPixel = outPixels[pixelIndex]; - // includes original translucence -- if there was -- - // overriding our gradient - //int srcAlpha = ALPHA; // all bits on - //if (srcHasAlpha) // baby got alpha from copyImage - //srcAlpha &= srcPixel; // only include src's alpha if the src has alpha; otherwise keep 'em on - int newPixel = - (thisGradient & ALPHA & srcPixel) | (srcPixel & RGB); - outPixels[pixelIndex] = newPixel; - } - pixelIndex++; - } // for i < width - } // for j < height - - } - protected ColorModel getColorModel(BufferedImage referenceImage) - { - return PixelBased.ARGB_MODEL; - } - protected SampleModel getSampleModel(BufferedImage referenceImage) - { - return new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, width, height, PixelBased.ARGB_MASKS); - } - public void paint(Graphics g, int x, int y) - { - super.paint(g, x, y); - } - - // for ORM layer: - - public float getRadius() - { - return radius; - } - - public void setRadius(float radius) - { - this.radius = radius; - } - - public int getMinAlpha() - { - return minAlpha; - } - - public void setMinAlpha(int minAlpha) - { - this.minAlpha = minAlpha; - } - @Override - protected void resizeImageComponents(int width, int height, boolean createBufferedImage) - { - double oldRadius = radius; - double ratio = Math.sqrt((double) (width * height) / (double) (this.width * this.height)); -// debug("resize ratio: " + oldRadius +"\t-> " + radius); - radius *= ratio; - super.resizeImageComponents(width, height, createBufferedImage); - } - - public int getMinAlphaInt() { - return minAlphaInt; - } - - public void setMinAlphaInt(int minAlphaInt) { - this.minAlphaInt = minAlphaInt; - } -} +package ecologylab.image; + +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.SampleModel; +import java.awt.image.SinglePixelPackedSampleModel; + +import ecologylab.generic.Colors; +import ecologylab.generic.ImageTools; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * @author andruid + * + * To change this generated comment edit the template variable "typecomment": + * Window>Preferences>Java>Templates. + * To enable and disable the creation of type comments go to + * Window>Preferences>Java>Code Generation. + */ +@simpl_inherit +public class AlphaGradientRendering extends Rendering +{ + @simpl_scalar + float radius; + + @simpl_scalar + int minAlpha; + + int minAlphaInt; + + public AlphaGradientRendering() + { + + } + +/** + * Constructor for AlphaGradientRendering. + * @param previousRendering + * @param active + */ + public AlphaGradientRendering(Rendering previousRendering, boolean active) + { + this(previousRendering, active, 0, ((int) (((float)0 / 255.0f) * (float) Colors.R)) & Colors.R ); + } + + public AlphaGradientRendering(Rendering previousRendering, boolean active, int radius, int minAlpha) + { + super(previousRendering, active); + this.radius = radius; + this.minAlpha = minAlpha; + minAlphaInt = 0; + } + + public void compute(int radius, int minAlpha) + { + this.radius = radius; + this.minAlpha = minAlpha; + doCompute(true, previousRendering); + isActive = true; + } + public void compute0(int[] inPixels, int[] outPixels) + { + fill(outPixels, G + B); + } + public void compute(Rendering inputRendering, Rendering outputRendering) + { + // cant use straight copy, because JPG images are read with 3 bands. + // if they dont get scaled, the source pixels may not have alpha set! + //System.arraycopy(inPixels, 0, outPixels, 0, inPixels.length); + + // let the graphics context do the copy, so it can smartly fix alpha + ImageTools.copyImage(inputRendering.bufferedImage, outputRendering.bufferedImage); + + int[] outPixels = outputRendering.pixels; + + // work in red space, to avoid signed arithmetic problems; + // shift up later + + // gradientMagnitude is the full delta of alpha, across the + // gradient area. + int gradientMagnitude = R - minAlpha; + int pixelIndex = 0; + int beyondRight = (int)(width - radius); // x >= places in gradient + int beyondBottom = (int)(height - radius);// y >= places in gradient + // debug("radius="+radius+ ", minAlpha="+Integer.toHexString(minAlpha) + + // ", gradientMagnitude="+hex(gradientMagnitude) + + // "\t"+width+"x"+height+"\n"); + for (int j=0; j= beyondBottom) + yFactor = height - j - 1; + for (int i=0; i= beyondRight) + xFactor = width - i - 1; + if (xFactor < gradientFactor) + gradientFactor = xFactor; + + if (gradientFactor < radius) + { + double gradientChange = ((float) gradientFactor / radius) * gradientMagnitude ; + int thisGradient = // shift to compensate for sign avoidance + ((int) gradientChange + minAlpha)<< 8; + + // !!! already blt-ed them all over + // int thisPixel = outPixels[pixelIndex]; + //int srcPixel = inPixels[pixelIndex]; + // note: input pixels have been copied to output pixels already! + int srcPixel = outPixels[pixelIndex]; + // includes original translucence -- if there was -- + // overriding our gradient + //int srcAlpha = ALPHA; // all bits on + //if (srcHasAlpha) // baby got alpha from copyImage + //srcAlpha &= srcPixel; // only include src's alpha if the src has alpha; otherwise keep 'em on + int newPixel = + (thisGradient & ALPHA & srcPixel) | (srcPixel & RGB); + outPixels[pixelIndex] = newPixel; + } + pixelIndex++; + } // for i < width + } // for j < height + + } + protected ColorModel getColorModel(BufferedImage referenceImage) + { + return PixelBased.ARGB_MODEL; + } + protected SampleModel getSampleModel(BufferedImage referenceImage) + { + return new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, width, height, PixelBased.ARGB_MASKS); + } + public void paint(Graphics g, int x, int y) + { + super.paint(g, x, y); + } + + // for ORM layer: + + public float getRadius() + { + return radius; + } + + public void setRadius(float radius) + { + this.radius = radius; + } + + public int getMinAlpha() + { + return minAlpha; + } + + public void setMinAlpha(int minAlpha) + { + this.minAlpha = minAlpha; + } + @Override + protected void resizeImageComponents(int width, int height, boolean createBufferedImage) + { + double oldRadius = radius; + double ratio = Math.sqrt((double) (width * height) / (double) (this.width * this.height)); +// debug("resize ratio: " + oldRadius +"\t-> " + radius); + radius *= ratio; + super.resizeImageComponents(width, height, createBufferedImage); + } + + public int getMinAlphaInt() { + return minAlphaInt; + } + + public void setMinAlphaInt(int minAlphaInt) { + this.minAlphaInt = minAlphaInt; + } +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/image/AreaAveragingScaleFilter.java b/simplSunSpecifics/src/ecologylab/image/AreaAveragingScaleFilter.java similarity index 95% rename from simplPlatformSpecifics/Sun/src/ecologylab/image/AreaAveragingScaleFilter.java rename to simplSunSpecifics/src/ecologylab/image/AreaAveragingScaleFilter.java index bd986c9f..0812383f 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/image/AreaAveragingScaleFilter.java +++ b/simplSunSpecifics/src/ecologylab/image/AreaAveragingScaleFilter.java @@ -1,183 +1,183 @@ -package ecologylab.image; - -public class AreaAveragingScaleFilter -{ - int srcWidth, srcHeight; - int destWidth, destHeight; - int[] outputRow; - - private float reds[], greens[], blues[], alphas[]; - private int savedy; - private int savedyrem; - - public AreaAveragingScaleFilter(int srcWidth, int srcHeight, - int destWidth, int destHeight, - int inputPixels[], int outputPixels[]) - { - this.srcWidth = srcWidth; - this.srcHeight = srcHeight; - this.destWidth = destWidth; - this.destHeight = destHeight; - - outputRow = new int[destWidth]; - - proc(inputPixels, outputPixels); - } - private void makeAccumBuffers() - { - reds = new float[destWidth]; - greens = new float[destWidth]; - blues = new float[destWidth]; - alphas = new float[destWidth]; - } - - private void calcRow() - { - float mult = ((float) srcWidth) * srcHeight; - - for (int x = 0; x < destWidth; x++) - { - int a = Math.round(alphas[x] / mult); - int r = Math.round(reds[x] / mult); - int g = Math.round(greens[x] / mult); - int b = Math.round(blues[x] / mult); - if (a < 0) {a = 0;} else if (a > 255) {a = 255;} - if (r < 0) {r = 0;} else if (r > 255) {r = 255;} - if (g < 0) {g = 0;} else if (g > 255) {g = 255;} - if (b < 0) {b = 0;} else if (b > 255) {b = 255;} - outputRow[x] = (a << 24 | r << 16 | g << 8 | b); - } - } - - private void accumPixels(int x, int y, int w, int h, - int[] inputPixels, int[] outputPixels, - int off, int scansize) - { - if (reds == null) - { - makeAccumBuffers(); - } - int sy = y; - int syrem = destHeight; - int dy, dyrem; - if (sy == 0) - { - dy = 0; - dyrem = 0; - } - else - { - dy = savedy; - dyrem = savedyrem; - } - while (sy < y + h) - { - int amty; - if (dyrem == 0) - { - for (int i = 0; i < destWidth; i++) - { - alphas[i] = reds[i] = greens[i] = blues[i] = 0f; - } - dyrem = srcHeight; - } - if (syrem < dyrem) - { - amty = syrem; - } - else - { - amty = dyrem; - } - int sx = 0; - int dx = 0; - int sxrem = 0; - int dxrem = srcWidth; - float a = 0f, r = 0f, g = 0f, b = 0f; - while (sx < w) - { - if (sxrem == 0) - { - sxrem = destWidth; - int rgb; - rgb = ((int[]) inputPixels)[off + sx]; - // rgb = model.getRGB(rgb); - a = rgb >>> 24; - r = (rgb >> 16) & 0xff; - g = (rgb >> 8) & 0xff; - b = rgb & 0xff; - } - int amtx; - if (sxrem < dxrem) - { - amtx = sxrem; - } - else - { - amtx = dxrem; - } - float mult = ((float) amtx) * amty; - alphas[dx] += mult * a; - reds[dx] += mult * r; - greens[dx] += mult * g; - blues[dx] += mult * b; - if ((sxrem -= amtx) == 0) - { - sx++; - } - if ((dxrem -= amtx) == 0) - { - dx++; - dxrem = srcWidth; - } - } - if ((dyrem -= amty) == 0) - { - calcRow(); - do - { - setOutput(outputPixels, dy); - dy++; - } while ((syrem -= amty) >= amty && amty == srcHeight); - } - else - { - syrem -= amty; - } - if (syrem == 0) - { - syrem = destHeight; - sy++; - off += scansize; - } - } - savedyrem = dyrem; - savedy = dy; - } - - /** - * Combine the components for the delivered int pixels into the - * accumulation arrays and send on any averaged data for rows of - * pixels that are complete. If the correct hints were not - * specified in the setHints call then relay the work to our - * superclass which is capable of scaling pixels regardless of - * the delivery hints. - *

- * Note: This method is intended to be called by the - * ImageProducer of the Image - * whose pixels are being filtered. Developers using - * this class to filter pixels from an image should avoid calling - * this method directly since that operation could interfere - * with the filtering operation. - */ - public void proc(int inputPixels[], int outputPixels[]) - { - accumPixels(0, 0, srcWidth, srcHeight, - inputPixels, outputPixels, - 0, srcWidth); - } - void setOutput(int outputPixels[], int rowNum) - { - System.arraycopy(outputRow, 0, outputPixels, rowNum*destWidth,destWidth); - } -} +package ecologylab.image; + +public class AreaAveragingScaleFilter +{ + int srcWidth, srcHeight; + int destWidth, destHeight; + int[] outputRow; + + private float reds[], greens[], blues[], alphas[]; + private int savedy; + private int savedyrem; + + public AreaAveragingScaleFilter(int srcWidth, int srcHeight, + int destWidth, int destHeight, + int inputPixels[], int outputPixels[]) + { + this.srcWidth = srcWidth; + this.srcHeight = srcHeight; + this.destWidth = destWidth; + this.destHeight = destHeight; + + outputRow = new int[destWidth]; + + proc(inputPixels, outputPixels); + } + private void makeAccumBuffers() + { + reds = new float[destWidth]; + greens = new float[destWidth]; + blues = new float[destWidth]; + alphas = new float[destWidth]; + } + + private void calcRow() + { + float mult = ((float) srcWidth) * srcHeight; + + for (int x = 0; x < destWidth; x++) + { + int a = Math.round(alphas[x] / mult); + int r = Math.round(reds[x] / mult); + int g = Math.round(greens[x] / mult); + int b = Math.round(blues[x] / mult); + if (a < 0) {a = 0;} else if (a > 255) {a = 255;} + if (r < 0) {r = 0;} else if (r > 255) {r = 255;} + if (g < 0) {g = 0;} else if (g > 255) {g = 255;} + if (b < 0) {b = 0;} else if (b > 255) {b = 255;} + outputRow[x] = (a << 24 | r << 16 | g << 8 | b); + } + } + + private void accumPixels(int x, int y, int w, int h, + int[] inputPixels, int[] outputPixels, + int off, int scansize) + { + if (reds == null) + { + makeAccumBuffers(); + } + int sy = y; + int syrem = destHeight; + int dy, dyrem; + if (sy == 0) + { + dy = 0; + dyrem = 0; + } + else + { + dy = savedy; + dyrem = savedyrem; + } + while (sy < y + h) + { + int amty; + if (dyrem == 0) + { + for (int i = 0; i < destWidth; i++) + { + alphas[i] = reds[i] = greens[i] = blues[i] = 0f; + } + dyrem = srcHeight; + } + if (syrem < dyrem) + { + amty = syrem; + } + else + { + amty = dyrem; + } + int sx = 0; + int dx = 0; + int sxrem = 0; + int dxrem = srcWidth; + float a = 0f, r = 0f, g = 0f, b = 0f; + while (sx < w) + { + if (sxrem == 0) + { + sxrem = destWidth; + int rgb; + rgb = ((int[]) inputPixels)[off + sx]; + // rgb = model.getRGB(rgb); + a = rgb >>> 24; + r = (rgb >> 16) & 0xff; + g = (rgb >> 8) & 0xff; + b = rgb & 0xff; + } + int amtx; + if (sxrem < dxrem) + { + amtx = sxrem; + } + else + { + amtx = dxrem; + } + float mult = ((float) amtx) * amty; + alphas[dx] += mult * a; + reds[dx] += mult * r; + greens[dx] += mult * g; + blues[dx] += mult * b; + if ((sxrem -= amtx) == 0) + { + sx++; + } + if ((dxrem -= amtx) == 0) + { + dx++; + dxrem = srcWidth; + } + } + if ((dyrem -= amty) == 0) + { + calcRow(); + do + { + setOutput(outputPixels, dy); + dy++; + } while ((syrem -= amty) >= amty && amty == srcHeight); + } + else + { + syrem -= amty; + } + if (syrem == 0) + { + syrem = destHeight; + sy++; + off += scansize; + } + } + savedyrem = dyrem; + savedy = dy; + } + + /** + * Combine the components for the delivered int pixels into the + * accumulation arrays and send on any averaged data for rows of + * pixels that are complete. If the correct hints were not + * specified in the setHints call then relay the work to our + * superclass which is capable of scaling pixels regardless of + * the delivery hints. + *

+ * Note: This method is intended to be called by the + * ImageProducer of the Image + * whose pixels are being filtered. Developers using + * this class to filter pixels from an image should avoid calling + * this method directly since that operation could interfere + * with the filtering operation. + */ + public void proc(int inputPixels[], int outputPixels[]) + { + accumPixels(0, 0, srcWidth, srcHeight, + inputPixels, outputPixels, + 0, srcWidth); + } + void setOutput(int outputPixels[], int rowNum) + { + System.arraycopy(outputRow, 0, outputPixels, rowNum*destWidth,destWidth); + } +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/image/BlurredRendering.java b/simplSunSpecifics/src/ecologylab/image/BlurredRendering.java similarity index 96% rename from simplPlatformSpecifics/Sun/src/ecologylab/image/BlurredRendering.java rename to simplSunSpecifics/src/ecologylab/image/BlurredRendering.java index b50c4050..1e8d3c34 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/image/BlurredRendering.java +++ b/simplSunSpecifics/src/ecologylab/image/BlurredRendering.java @@ -1,157 +1,157 @@ -package ecologylab.image; - -/** - * Image buffer state that applies a blur filter to the pixels chained - * in. - */ -public class BlurredRendering extends Rendering -{ - int blurWidth; - int blurHeight; - - int[] sumR, sumG, sumB; // single row or column buffers - -/** - * Constructor for BlurredRendering. - * @param previousRendering The previous state in the rendering chain. - * @param active This state may be turned off. - */ - public BlurredRendering(Rendering previousRendering, boolean active) - { - super(previousRendering, active); - isDynamic = true; - } - public BlurredRendering(Rendering previousRendering, Rendering nextRendering, boolean active) - { - super(previousRendering, nextRendering, active); - isDynamic = true; - } - - public void compute(int bWidth, int bHeight, boolean immediate) - { - // debug("compute("+(immediate ? "immediate":"later")); - boolean goingInactive = false; - if ((bWidth == 0) || (bHeight == 0)) - { - if ((blurWidth == 0) || (blurHeight == 0)) - { - debug(".compute() does nothing. blurRadius=0"); - return; - } - else - { - goingInactive = true; - } - } - else if ((bWidth == blurWidth) && (bHeight == blurHeight)) - return; - - blurWidth = bWidth; - blurHeight = bHeight; - setPending(); - - isActive = !goingInactive; - - // debug("compute(isActive="+isActive); - if (immediate) - { - if (goingInactive) - goInactive(true); - else - compute(true); - } - } - public void compute(Rendering inputRendering, Rendering outputRendering) - { - int[] inPixels = inputRendering.pixels; - int[] outPixels = outputRendering.pixels; - - // int n = Math.max(width,height); - int n = (width > height) ? width : height; - // ??? kludges to workaround bizarre alloc problems !!! why?????? - if ((sumR == null) || (sumR.length != n)) - sumR = new int[n]; - if ((sumG == null) || (sumG.length != n)) - sumG = new int[n]; - if ((sumB == null) || (sumB.length != n)) - sumB = new int[n]; - - for (int j=0; j<2; j++) - { - // blur vertical up and down each line - for (int i=0; i< width; i++) - try - { - blur1D(i, false, blurHeight, height, inPixels, outPixels); - } catch (ArrayIndexOutOfBoundsException e) - { - pixelBased.debug("??????BlurException! i="+i+ " blurHeight="+ - blurHeight+ - " "+width+"x"+height+ " sumR.length="+sumR.length + - " sumG.length="+sumG.length + - " sumB.length="+sumB.length + - " inPixels.length="+inPixels.length + - " outPixels.length="+outPixels.length); - e.printStackTrace(); - return; // !!! punt blur !!! - } - // blur horizontal across each raster - for (int i=0; i< height; i++) - blur1D(i, true, blurWidth, width, inPixels, outPixels); - } - } - public void blur1D(int rasterNum, boolean horizontal, - int blurRadius, int n, - int[] inPix, int[] outPix) - { - int origin = horizontal ? rasterNum * width : rasterNum; - int delta = horizontal ? 1 : width; - - // Debug.println((horizontal ? "horizontal" : "vertical") + " rasterNum="+ - // rasterNum + " n="+n+" origin="+origin+" delta="+delta); - - // sum up all the values: - sumR[0] = (inPix[origin] & R) >> 16; - sumG[0] = (inPix[origin] & G) >> 8; - sumB[0] = inPix[origin] & B; - int index = origin; - for (int i = 1 ; i < n ; i++) - { - if (index < 0 || index >= inPix.length) - { - System.err.println("\nIndex = " + index ); - } - int thisPixel = inPix[index]; - sumR[i] = sumR[i-1] + ((thisPixel & R) >> 16); - sumG[i] = sumG[i-1] + ((thisPixel & G) >> 8); - sumB[i] = sumB[i-1] + (thisPixel & B); - index += delta; - } - - // take differences to create blurring by a box filter - // with some particular blur radius. - index = origin; - n--; // use this value for iHi and loop bound <= - for (int i = 0 ; i <= n ; i++) - { - // int iLo = Math.max(i - blurRadius, 0); - // int iHi = Math.min(i + blurRadius, n); - int iLo = i - blurRadius; - if (iLo < 0) - iLo = 0; - int iHi = i + blurRadius; - if (iHi > n) - iHi = n; - int divisor = iHi - iLo; - if (divisor > 1) - { - int thisPixel = inPix[index]; - int r = (sumR[iHi] - sumR[iLo]) / divisor; - int g = (sumG[iHi] - sumG[iLo]) / divisor; - int b = (sumB[iHi] - sumB[iLo]) / divisor; - outPix[index] = (ALPHA & inPix[index]) + (r << 16) + (g << 8) + b; - } - index += delta; - } - } -} +package ecologylab.image; + +/** + * Image buffer state that applies a blur filter to the pixels chained + * in. + */ +public class BlurredRendering extends Rendering +{ + int blurWidth; + int blurHeight; + + int[] sumR, sumG, sumB; // single row or column buffers + +/** + * Constructor for BlurredRendering. + * @param previousRendering The previous state in the rendering chain. + * @param active This state may be turned off. + */ + public BlurredRendering(Rendering previousRendering, boolean active) + { + super(previousRendering, active); + isDynamic = true; + } + public BlurredRendering(Rendering previousRendering, Rendering nextRendering, boolean active) + { + super(previousRendering, nextRendering, active); + isDynamic = true; + } + + public void compute(int bWidth, int bHeight, boolean immediate) + { + // debug("compute("+(immediate ? "immediate":"later")); + boolean goingInactive = false; + if ((bWidth == 0) || (bHeight == 0)) + { + if ((blurWidth == 0) || (blurHeight == 0)) + { + debug(".compute() does nothing. blurRadius=0"); + return; + } + else + { + goingInactive = true; + } + } + else if ((bWidth == blurWidth) && (bHeight == blurHeight)) + return; + + blurWidth = bWidth; + blurHeight = bHeight; + setPending(); + + isActive = !goingInactive; + + // debug("compute(isActive="+isActive); + if (immediate) + { + if (goingInactive) + goInactive(true); + else + compute(true); + } + } + public void compute(Rendering inputRendering, Rendering outputRendering) + { + int[] inPixels = inputRendering.pixels; + int[] outPixels = outputRendering.pixels; + + // int n = Math.max(width,height); + int n = (width > height) ? width : height; + // ??? kludges to workaround bizarre alloc problems !!! why?????? + if ((sumR == null) || (sumR.length != n)) + sumR = new int[n]; + if ((sumG == null) || (sumG.length != n)) + sumG = new int[n]; + if ((sumB == null) || (sumB.length != n)) + sumB = new int[n]; + + for (int j=0; j<2; j++) + { + // blur vertical up and down each line + for (int i=0; i< width; i++) + try + { + blur1D(i, false, blurHeight, height, inPixels, outPixels); + } catch (ArrayIndexOutOfBoundsException e) + { + pixelBased.debug("??????BlurException! i="+i+ " blurHeight="+ + blurHeight+ + " "+width+"x"+height+ " sumR.length="+sumR.length + + " sumG.length="+sumG.length + + " sumB.length="+sumB.length + + " inPixels.length="+inPixels.length + + " outPixels.length="+outPixels.length); + e.printStackTrace(); + return; // !!! punt blur !!! + } + // blur horizontal across each raster + for (int i=0; i< height; i++) + blur1D(i, true, blurWidth, width, inPixels, outPixels); + } + } + public void blur1D(int rasterNum, boolean horizontal, + int blurRadius, int n, + int[] inPix, int[] outPix) + { + int origin = horizontal ? rasterNum * width : rasterNum; + int delta = horizontal ? 1 : width; + + // Debug.println((horizontal ? "horizontal" : "vertical") + " rasterNum="+ + // rasterNum + " n="+n+" origin="+origin+" delta="+delta); + + // sum up all the values: + sumR[0] = (inPix[origin] & R) >> 16; + sumG[0] = (inPix[origin] & G) >> 8; + sumB[0] = inPix[origin] & B; + int index = origin; + for (int i = 1 ; i < n ; i++) + { + if (index < 0 || index >= inPix.length) + { + System.err.println("\nIndex = " + index ); + } + int thisPixel = inPix[index]; + sumR[i] = sumR[i-1] + ((thisPixel & R) >> 16); + sumG[i] = sumG[i-1] + ((thisPixel & G) >> 8); + sumB[i] = sumB[i-1] + (thisPixel & B); + index += delta; + } + + // take differences to create blurring by a box filter + // with some particular blur radius. + index = origin; + n--; // use this value for iHi and loop bound <= + for (int i = 0 ; i <= n ; i++) + { + // int iLo = Math.max(i - blurRadius, 0); + // int iHi = Math.min(i + blurRadius, n); + int iLo = i - blurRadius; + if (iLo < 0) + iLo = 0; + int iHi = i + blurRadius; + if (iHi > n) + iHi = n; + int divisor = iHi - iLo; + if (divisor > 1) + { + int thisPixel = inPix[index]; + int r = (sumR[iHi] - sumR[iLo]) / divisor; + int g = (sumG[iHi] - sumG[iLo]) / divisor; + int b = (sumB[iHi] - sumB[iLo]) / divisor; + outPix[index] = (ALPHA & inPix[index]) + (r << 16) + (g << 8) + b; + } + index += delta; + } + } +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/image/BufferedPhoto.java b/simplSunSpecifics/src/ecologylab/image/BufferedPhoto.java similarity index 95% rename from simplPlatformSpecifics/Sun/src/ecologylab/image/BufferedPhoto.java rename to simplSunSpecifics/src/ecologylab/image/BufferedPhoto.java index af49aea3..0e02081f 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/image/BufferedPhoto.java +++ b/simplSunSpecifics/src/ecologylab/image/BufferedPhoto.java @@ -1,38 +1,38 @@ -/* - * Written by Eunyee Koh. - */ -package ecologylab.image; - -import java.awt.Dimension; -import java.awt.image.BufferedImage; - -/* - * Create this constructor for Buffered Images, which do not need to download. - * So, download method do nothing. - * - * @author eunyee - * - * TODO To change the template for this generated type comment go to - * Window - Preferences - Java - Code Style - Code Templates - */ -public class BufferedPhoto -extends PixelBased -{ - boolean aborted; - - public BufferedPhoto(BufferedImage bufferedImage, Dimension maxDimension) - { - super(bufferedImage, maxDimension); - } - public boolean download() - { - return true; -// debug("download() does nothing"); - } - - protected void rescaleImage() - { - - } -} - +/* + * Written by Eunyee Koh. + */ +package ecologylab.image; + +import java.awt.Dimension; +import java.awt.image.BufferedImage; + +/* + * Create this constructor for Buffered Images, which do not need to download. + * So, download method do nothing. + * + * @author eunyee + * + * TODO To change the template for this generated type comment go to + * Window - Preferences - Java - Code Style - Code Templates + */ +public class BufferedPhoto +extends PixelBased +{ + boolean aborted; + + public BufferedPhoto(BufferedImage bufferedImage, Dimension maxDimension) + { + super(bufferedImage, maxDimension); + } + public boolean download() + { + return true; +// debug("download() does nothing"); + } + + protected void rescaleImage() + { + + } +} + diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/image/DesaturatedRendering.java b/simplSunSpecifics/src/ecologylab/image/DesaturatedRendering.java similarity index 95% rename from simplPlatformSpecifics/Sun/src/ecologylab/image/DesaturatedRendering.java rename to simplSunSpecifics/src/ecologylab/image/DesaturatedRendering.java index 94819140..ce4de8f5 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/image/DesaturatedRendering.java +++ b/simplSunSpecifics/src/ecologylab/image/DesaturatedRendering.java @@ -1,107 +1,107 @@ -package ecologylab.image; - -import ecologylab.generic.ImageTools; - -/** - * Rendering that applies a desaturating filter to the pixels chained in. - */ -public class DesaturatedRendering extends Rendering -{ - static final float MIN_DESAT = .07f; - - float degree; - - /** - * Constructor for DesaturatedRendering. - * - * @param suppliedPixels - * @param previousRendering - * @param active - */ - public DesaturatedRendering(Rendering previousRendering, boolean active) - { - super(previousRendering, active); - -// setupImageComponents(width, height); -// ImageTools.copyImage(previousRendering.bufferedImage, bufferedImage); - isDynamic = true; - } - - public void compute(float degreeArg, boolean immediate) - { - boolean goingInactive = false; - if (degreeArg < MIN_DESAT) - { - degreeArg = 0; - if (degree < MIN_DESAT) - { - debug(".desaturate does nothing. degree=" + degreeArg); - return; - } - else - { - goingInactive = true; - debug("compute(goingInactive isActive=" + isActive + " degree= " + degree + " -> " - + degreeArg); - } - } - else if (degreeArg == degree) - return; - - isActive = !goingInactive; - // debug("compute(isActive="+isActive+" degree= "+degree+" -> "+degreeArg); - degree = degreeArg; - setPending(); - - if (immediate) - { - if (goingInactive) - goInactive(true); - else - compute(true); - } - } - - public void compute(float degree) - { - this.degree = degree; - doCompute(true, previousRendering); - isActive = true; - } - - public void compute(Rendering inputRendering, Rendering outputRendering) - { - ImageTools.copyImage(inputRendering.bufferedImage, outputRendering.bufferedImage); - - int[] outPixels = outputRendering.pixels(); - - int pixelIndex = 0; - float oneMinusDegree = 1 - degree; - for (int j = 0; j < height; j++) - { - for (int i = 0; i < width; i++) - { - int thisPixel = outPixels[pixelIndex]; - int r = (thisPixel & R) >> 16; - int g = (thisPixel & G) >> 8; - int b = thisPixel & B; - boolean alreadyGray = (r == g) && (r == b) && (g == b); - if (!alreadyGray) - { - // int max = Math.max(Math.max(r,g), b); - int max = (r > g) ? r : g; - max = (b > max) ? b : max; - // float gray = degree * max; - int gray = (int) (degree * max); - // fold in a weighted amount of grey - r = (int) (gray + oneMinusDegree * r); - g = (int) (gray + oneMinusDegree * g); - b = (int) (gray + oneMinusDegree * b); - int alpha = thisPixel & ALPHA; - outPixels[pixelIndex] = alpha + (r << 16) + (g << 8) + b; - } - pixelIndex++; - } - } - } -} +package ecologylab.image; + +import ecologylab.generic.ImageTools; + +/** + * Rendering that applies a desaturating filter to the pixels chained in. + */ +public class DesaturatedRendering extends Rendering +{ + static final float MIN_DESAT = .07f; + + float degree; + + /** + * Constructor for DesaturatedRendering. + * + * @param suppliedPixels + * @param previousRendering + * @param active + */ + public DesaturatedRendering(Rendering previousRendering, boolean active) + { + super(previousRendering, active); + +// setupImageComponents(width, height); +// ImageTools.copyImage(previousRendering.bufferedImage, bufferedImage); + isDynamic = true; + } + + public void compute(float degreeArg, boolean immediate) + { + boolean goingInactive = false; + if (degreeArg < MIN_DESAT) + { + degreeArg = 0; + if (degree < MIN_DESAT) + { + debug(".desaturate does nothing. degree=" + degreeArg); + return; + } + else + { + goingInactive = true; + debug("compute(goingInactive isActive=" + isActive + " degree= " + degree + " -> " + + degreeArg); + } + } + else if (degreeArg == degree) + return; + + isActive = !goingInactive; + // debug("compute(isActive="+isActive+" degree= "+degree+" -> "+degreeArg); + degree = degreeArg; + setPending(); + + if (immediate) + { + if (goingInactive) + goInactive(true); + else + compute(true); + } + } + + public void compute(float degree) + { + this.degree = degree; + doCompute(true, previousRendering); + isActive = true; + } + + public void compute(Rendering inputRendering, Rendering outputRendering) + { + ImageTools.copyImage(inputRendering.bufferedImage, outputRendering.bufferedImage); + + int[] outPixels = outputRendering.pixels(); + + int pixelIndex = 0; + float oneMinusDegree = 1 - degree; + for (int j = 0; j < height; j++) + { + for (int i = 0; i < width; i++) + { + int thisPixel = outPixels[pixelIndex]; + int r = (thisPixel & R) >> 16; + int g = (thisPixel & G) >> 8; + int b = thisPixel & B; + boolean alreadyGray = (r == g) && (r == b) && (g == b); + if (!alreadyGray) + { + // int max = Math.max(Math.max(r,g), b); + int max = (r > g) ? r : g; + max = (b > max) ? b : max; + // float gray = degree * max; + int gray = (int) (degree * max); + // fold in a weighted amount of grey + r = (int) (gray + oneMinusDegree * r); + g = (int) (gray + oneMinusDegree * g); + b = (int) (gray + oneMinusDegree * b); + int alpha = thisPixel & ALPHA; + outPixels[pixelIndex] = alpha + (r << 16) + (g << 8) + b; + } + pixelIndex++; + } + } + } +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/image/Makefile b/simplSunSpecifics/src/ecologylab/image/Makefile similarity index 95% rename from simplPlatformSpecifics/Sun/src/ecologylab/image/Makefile rename to simplSunSpecifics/src/ecologylab/image/Makefile index 15d4b03c..1f797a29 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/image/Makefile +++ b/simplSunSpecifics/src/ecologylab/image/Makefile @@ -1,28 +1,28 @@ -DIR = cs/media - -JAVA_SRC = PixelBased.java ImageState.java \ - AlphaGradientState.java BlurState.java \ - DesaturateState.java AreaAveragingScaleFilter.java \ - IIOPhoto.java Sound.java BufferedPhoto.java - - -# QTTools.java QTMovie.java - -# PhotoI.java Picture.java Icon.java FilmLoop.java Sound.java Text.java -#ToolBar.java ChoiceBar.java -# SoundPlay.java DesaturateFilter.java PhotoXform.java - -JAVA_ROOT=../../ - -PACKAGE_CLASS = $(PACKAGE_SRC:%.java=%.class) - -MAKE_DIR = ../../../../makefiles -include $(MAKE_DIR)/applets.make - -cabsign: all - -nsjar: all - -qtmovie: $(JAVA_CLASS) - $(JAVA) cm.media.QTMovie - +DIR = cs/media + +JAVA_SRC = PixelBased.java ImageState.java \ + AlphaGradientState.java BlurState.java \ + DesaturateState.java AreaAveragingScaleFilter.java \ + IIOPhoto.java Sound.java BufferedPhoto.java + + +# QTTools.java QTMovie.java + +# PhotoI.java Picture.java Icon.java FilmLoop.java Sound.java Text.java +#ToolBar.java ChoiceBar.java +# SoundPlay.java DesaturateFilter.java PhotoXform.java + +JAVA_ROOT=../../ + +PACKAGE_CLASS = $(PACKAGE_SRC:%.java=%.class) + +MAKE_DIR = ../../../../makefiles +include $(MAKE_DIR)/applets.make + +cabsign: all + +nsjar: all + +qtmovie: $(JAVA_CLASS) + $(JAVA) cm.media.QTMovie + diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/image/PixelBased.java b/simplSunSpecifics/src/ecologylab/image/PixelBased.java similarity index 95% rename from simplPlatformSpecifics/Sun/src/ecologylab/image/PixelBased.java rename to simplSunSpecifics/src/ecologylab/image/PixelBased.java index 3934d437..9ceae3ca 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/image/PixelBased.java +++ b/simplSunSpecifics/src/ecologylab/image/PixelBased.java @@ -1,896 +1,897 @@ -package ecologylab.image; - -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Toolkit; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.awt.image.DirectColorModel; -import java.awt.image.PackedColorModel; -import java.io.IOException; -import java.net.URL; - -import ecologylab.concurrent.BasicSite; -import ecologylab.concurrent.Downloadable; -import ecologylab.concurrent.DownloadableLogRecord; -import ecologylab.generic.Colors; -import ecologylab.generic.ConsoleUtils; -import ecologylab.generic.MathTools; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_classes; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_wrap; - -/** - * Infrastructure to display, keep track of, and manipulate pixel based media. - * - * Works with {@link Rendering Rendering} to implement pipelined - * image processing transformations on the bits. - */ -@simpl_inherit -public class PixelBased -extends ElementState -implements Downloadable, Colors -{ - - // /////////////////////////// image transform state //////////////////////// - public static final int NO_ALPHA_RADIUS = -1; - - protected static final DirectColorModel ARGB_MODEL = new DirectColorModel(32, 0x00ff0000, 0x0000ff00, 0xff, 0xff000000); - - protected static final PackedColorModel RGB_MODEL = new DirectColorModel(24, 0xff0000, 0xff00, 0xff, 0); - - protected static final int[] ARGB_MASKS = { 0xff0000, 0xff00, 0xff, 0xff000000, }; - - protected static final int[] RGB_MASKS = { 0xff0000, 0xff00, 0xff, }; - - static final int[] RGB_BANDS = { 0, 1, 2 }; - - /** - * Net location of the whatever might get downloaded. Change from URL to ParsedURL. - */ - ParsedURL purl; - - boolean recycled; - - /** - * Don't run grab() more than once. - */ - boolean grabbed; ; - - /** - * like unprocessedRendering, but never part of a chain. image buffer for the completely - * unaltered, the virgin. Usually unscaled, but may be scaled down due to maxDimension, - */ - @simpl_composite - @simpl_classes({ AlphaGradientRendering.class, Rendering.class, DesaturatedRendering.class, BlurredRendering.class }) - @simpl_wrap - Rendering basisRendering; - - /** - * No image processing on this rendering, but if there is scaling to do, this one is scaled. - */ -// @simpl_classes({ AlphaGradientRendering.class, Rendering.class, DesaturatedRendering.class, BlurredRendering.class }) -// @simpl_wrap - protected Rendering unprocessedRendering; - - @simpl_composite - AlphaGradientRendering alphaGradientRendering; - - @simpl_composite - BlurredRendering blurredRendering; - - @simpl_composite - DesaturatedRendering desaturatedRendering; - - /** - * The current Rendering. - */ - @simpl_composite - @simpl_classes({ AlphaGradientRendering.class, Rendering.class, DesaturatedRendering.class, BlurredRendering.class }) - @simpl_wrap - Rendering currentRendering; - - public final Object renderingsLock = new Object(); - - /** - * First Rendering in the pipeline (chain) that is dynamic, that is, that changes after 1st - * rendered. - */ - Rendering firstDynamic; - - private long ormId; - - /** - * Size of the image, once we know it. Position, as well, if its on screen. - */ - // protected Dimension dimension = new Dimension(); - @simpl_scalar - protected int width; - - @simpl_scalar - protected int height; - - // ////////////////////// for debugging //////////////////////////////// - @simpl_scalar - boolean scaled; - - public static int constructedCount, recycledCount; - - public Rendering getFirstDynamic() - { - return firstDynamic; - } - - /////////////////////// constructors ////////////////////////// - public PixelBased() - { - - } - - public PixelBased(BufferedImage bufferedImage) - { - this(bufferedImage, null); - } - public PixelBased(BufferedImage bufferedImage, Dimension maxDimension) - { - if (maxDimension == null) - maxDimension = new Dimension(bufferedImage.getWidth(), bufferedImage.getHeight()); - - Rendering rendering = new Rendering(this, bufferedImage, null, null); - - rendering = scaleRenderingUnderMaxDimension(rendering, rendering.width, rendering.height, maxDimension); - - initializeRenderings(rendering); - - constructedCount++; - } - - public void initializeRenderings(Rendering rendering) - { - width = rendering.width; - height = rendering.height; - basisRendering = rendering; - currentRendering = rendering; - } - - - protected Rendering scaleRenderingUnderMaxDimension(Rendering rendering, - int width, int height, Dimension maxDimension) - { - if( maxDimension!= null ) - { - int maxWidth = maxDimension.width; - int maxHeight = maxDimension.height; - if (width > maxWidth || height > maxHeight) - { - if (width / (float) height < maxWidth / (float) maxHeight) - { - width = (width*maxHeight + height/2) / height; - height = maxHeight; - } - else - { - height = (height*maxWidth + width/2) / width; - width = maxWidth; - } - Rendering origRendering = rendering; - if (width > 0 && height > 0) - { - rendering = rendering.getScaledRendering(width, height); - } - origRendering.recycle(); - origRendering = null; - } - } - return rendering; - } -//////////////////////from regular Image -> int[] pixels ///////////////////// - /** - * If possible, grab the image into memory. This is required for all - * image processing operations. - * This method creates the unprocessed Rendering " + -// newWidth +","+ newHeight); - if (recycled || (basisRendering == null)) - return false; - - if ((bufferedImage.getWidth() != newWidth) || (newHeight != bufferedImage.getHeight())) - { - if (unprocessedRendering == null) - { - synchronized (renderingsLock) - { - width = newWidth; - height = newHeight; - scaled = true; - unprocessedRendering = basisRendering.getScaledRendering(newWidth, newHeight); -// basisRendering = basisRendering.getScaledRendering(newWidth, newHeight); -// unprocessedRendering = new Rendering(basisRendering); - } - } - else - { - //ConsoleUtils.obtrusiveConsoleOutput("Resize in scaleInitially()! " + this + " " + dimension+ - // " ->"+newWidth+","+newHeight); - if ((this.alphaGradientRendering != null) && (this.unprocessedRendering.nextRendering != alphaGradientRendering)) - { - ConsoleUtils.obtrusiveConsoleOutput("GASP! alphaGradient is not in the pipeline chain!"); - } - this.resize(newWidth, newHeight); - if ((this.alphaGradientRendering != null) && (alphaGradientRendering.width != width)) - ConsoleUtils.obtrusiveConsoleOutput("EARLY CRAZY! this="+width+" alphaGrad="+this.alphaGradientRendering.width); - - } - } - else - { - // create new Rendering using the same pixels, DataBufferInt, BufferedImage - // this is efficient! - //ConsoleUtils.obtrusiveConsoleOutput("No Scaling! " + this + " " + dimension); - if (unprocessedRendering == null) - unprocessedRendering = new Rendering(basisRendering); - //unprocessedRendering = unscaledRendering.getScaledRendering(newWidth, newHeight); - } - - this.setCurrentRendering(unprocessedRendering); - return true; - } - public void dontScaleInitially() - { - if (!recycled && (basisRendering != null)) - { - // create new Rendering using the same pixels, DataBufferInt, BufferedImage - // this is efficient! - if (unprocessedRendering == null) - unprocessedRendering = new Rendering(basisRendering); - this.setCurrentRendering(unprocessedRendering); - } - } - public boolean resize(int newWidth, int newHeight) - { - // debug("scale() " + extent.width +","+ extent.height+" -> " + - // newWidth +","+ newHeight); - if (recycled) - return false; - - if ((newWidth != width) || (newHeight != height)) - { - if (unprocessedRendering == null) - { - unprocessedRendering = new Rendering(basisRendering); - this.setCurrentRendering(unprocessedRendering); - } - - synchronized (renderingsLock) - { - width = newWidth; - height = newHeight; - scaled = true; - unprocessedRendering.resize(newWidth, newHeight, basisRendering); -// if (alphaGradientRendering != null) -// { -// unprocessedRendering.computeNext(); -// } - } - } - return true; - } - - public void setupRandomAlphaGradient(float radiusFactor) - { - // now (after probability thresholding), push it up! - radiusFactor = MathTools.bias(radiusFactor, .7f); - int shorter = (width < height) ? width : height; - int alphaRadius = (int) ((shorter / 2) * radiusFactor); - int alphaMinimum = ((int) (MathTools.random(.4f) * (float) R)) & R; - - alphaGradient(alphaRadius, alphaMinimum); - } - /** - * Builds an alpha gradient, or feathered mask. - * - * Acts on buffer in the pixels slot. - * - * @param radius area -- pixels of border to mask - * @param minAlpha lowest alpha setting in mask -- represented in - * red, instead of alpha space, to avoid - * signed arithmetic problems; will shift up later - */ - public boolean alphaGradient(int radius, int minAlpha) - { - if (recycled) - return false; - - if (unprocessedRendering == null) - unprocessedRendering = new Rendering(basisRendering); - - boolean active = (radius != NO_ALPHA_RADIUS); - - if (alphaGradientRendering == null) - alphaGradientRendering = new AlphaGradientRendering(unprocessedRendering, active); - - if (active) - { - alphaGradientRendering.compute(radius, minAlpha); - Rendering last = alphaGradientRendering.lastActive(); - if (last == alphaGradientRendering) - //alphaGradientState.hookup(); - this.setCurrentRendering(alphaGradientRendering); - else - // last.compute(); - alphaGradientRendering.computeNext(); - } - if (alphaGradientRendering.width != width) - ConsoleUtils.obtrusiveConsoleOutput("CRAZY! this="+width+" alphaGrad="+this.alphaGradientRendering.width); - return true; - } - - public boolean alphaGradient(int radius, int minAlpha, int minAlphaInt) - { - alphaGradientRendering.setMinAlphaInt(minAlphaInt); - return alphaGradient(radius, minAlpha); - } - - /** - * @return In alpha gradient blending, the distance from the perimeter, - * inside which opacity is complete. - */ - public double alphaRadius() - { - return (alphaGradientRendering != null) ? alphaGradientRendering.radius : 0; - } - /** - * @return the minimum value opacity mask used for alpha gradient blending. - * [0, 255] - */ - public int minAlpha() - { - return (alphaGradientRendering != null) ? alphaGradientRendering.minAlpha : 0; - } - public boolean hasAlphaGradient() - { - return (alphaGradientRendering != null) && alphaGradientRendering.isActive; - } - public void blur2D(int blurWidth, int blurHeight, boolean immediate) - { - if (recycled || (unprocessedRendering == null)) - return; - synchronized (renderingsLock) - { - if (blurredRendering == null) - { - if (desaturatedRendering == null) - blurredRendering = new BlurredRendering(lastStatic(), true); - else - blurredRendering = new BlurredRendering(lastStatic(), desaturatedRendering, - true); - firstDynamic = blurredRendering; - } - - blurredRendering.compute(blurWidth, blurHeight, false); - blurredRendering.goActive(immediate); - - /* blurState.goActive(); - blurState.compute(blurWidth, blurHeight, immediate); - if (immediate && blurState.isLastActive()) - blurState.hookup(); - */ - } - } - public void noAlphaGradient() - { - this.setCurrentRendering(unprocessedRendering); - unprocessedRendering.recycleRenderingChain(false); - unprocessedRendering.nextRendering = null; - alphaGradientRendering = null; - desaturatedRendering = null; - //goInactive(alphaGradientRendering); - } - public boolean restoreAlphaGradient() - { - boolean result = alphaGradientRendering != null; - if (result) - { - alphaGradientRendering.fixPreviousRendering(unprocessedRendering); // kludge pipeline if necessary - goActive(alphaGradientRendering, true); - } - return result; - } - public void noBlur2D() - { - goInactive(blurredRendering); - } - public void blur2D(float degree, boolean immediate) - { - // for more perceptibly linear response, push degree toward 0 - // degree = MoreMath.bias(degree, .4f); - int blurWidth = (int) ((float) width * .25f * degree); - int blurHeight = (int) ((float) height * .25f * degree); - blur2D(blurWidth, blurHeight, immediate); - } - /** - * @param degree degree of desaturation - */ - public void desaturate(float degree, boolean immediate) - { - if (show(1)) - debug("desaturate("+degree+") " + immediate); - if (recycled || (unprocessedRendering == null)) - return; - if (degree < .07f) - return; - - Rendering blurredRendering = this.blurredRendering; - synchronized (renderingsLock) - { - if (desaturatedRendering == null) - { - if (blurredRendering == null) - { - desaturatedRendering - = new DesaturatedRendering(lastStatic(), true); - // = new DesaturateState(this, alphaGradientState, true); - firstDynamic= desaturatedRendering; - } - else - { - desaturatedRendering - = new DesaturatedRendering(blurredRendering, true); - } - } - if ((blurredRendering != null) && (blurredRendering.previousRendering == null)) - throw new RuntimeException(this + " changed to NULL previousRendering?????);by new DesaturatedRendering"); - - desaturatedRendering.compute(degree); - //desaturatedRendering.goActive(immediate); - setCurrentRendering(desaturatedRendering); - } - } - public void noDesaturate() - { - goInactive(desaturatedRendering); - } - - - /////////////////////// Rendering management ////////////////////////// - void goInactive(Rendering rendering) - { - if (!recycled && (rendering != null)) - rendering.goInactive(); - } - void goActive(Rendering rendering, boolean immediate) - { - if (!recycled && (rendering != null)) - rendering.goActive(immediate); - } - boolean useNoProc; - public void setUseNoProc(boolean value) - { - useNoProc = value; - } - - /////////////////////// Images and MemoryImageSource ////////////////////////// - - public void setCurrentRendering(Rendering rendering) - { - if (!recycled) - this.currentRendering = rendering; - } -////////////////////////sundry services //////////////////////////////// - public Cursor createCustomCursor(Point point, String name) - { - return createCustomCursor(basisRendering.bufferedImage, point, name); - } - - public static Cursor createCustomCursor(BufferedImage bufferedImage, Point point, String name) - { - Toolkit kit = Toolkit.getDefaultToolkit(); - return kit.createCustomCursor(bufferedImage, point, name); - } - -////////////////////////rendering //////////////////////////////// - - Rendering lastStatic() - { - return (alphaGradientRendering == null) ? unprocessedRendering : alphaGradientRendering; - } - /** - * rendering - */ - public void paint(Graphics g, int x, int y) - { - if (!recycled) - { - Rendering rendering = useNoProc ? this.unprocessedRendering : this.currentRendering; - if (rendering != null) - rendering.paint(g, x, y); - //else - //debug("ERROR: trying to render, but no current rendering"); - } - } - public void paint(Graphics2D g2, int x, int y, AffineTransform a) - { - if (!recycled) - { - Rendering rendering = useNoProc ? this.unprocessedRendering : this.currentRendering; - if (rendering != null) - rendering.paint(g2, x, y, a); - //else - //debug("ERROR: trying to render, but no current rendering"); - } - } - -////////////////////////utilities //////////////////////////////// - public String toString() - { - String addr = "["+ ((purl==null) ? "no purl - " + this.getClassSimpleName() : purl.toString())+"]"; - String dim = "[" + width+"x"+height + "] "; - return getClassSimpleName(this) + addr + dim; - } - public String errorMessage() - { - String purlString = (purl == null) ? "null" : purl.toString(); - return "** " + getClassSimpleName() + " can't access content: " + purlString; - } - - public static String hex(int h) - { - return Integer.toHexString(h) + " "; - } - - /** - * Encourage resource relamation -- flush Image and - * release Rendering buffers.. - */ - public void recycle() - { - synchronized (renderingsLock) - { - if (!recycled) - { - //debug("recycle()"); - recycled = true; - - purl = null; - - if (unprocessedRendering != null) - { - unprocessedRendering.recycleRenderingChain(true); - unprocessedRendering.recycle(); // also calls chain of Renderings - unprocessedRendering = null; - } - - if (currentRendering != null) - { - currentRendering.recycle(); - currentRendering = null; - } - - if (firstDynamic != null) - { - firstDynamic.recycle(); - firstDynamic = null; - } - - if (basisRendering != null) - { - basisRendering.recycle(); - basisRendering = null; - } - - if (this.alphaGradientRendering != null) - { - alphaGradientRendering.recycle(); - alphaGradientRendering = null; - } - if (this.desaturatedRendering != null) - { - desaturatedRendering.recycle(); - desaturatedRendering = null; - } - if (this.blurredRendering != null) - { - blurredRendering.recycle(); - blurredRendering = null; - } - recycledCount++; - } - } - } - - /** - * Debugging info about the status of the image. - */ - public String downScaled() - { - String scale= scaled ? " scaled" : ""; - return scale; - } - - /** - * A shorter string for displaing in the modeline for debugging, and - in popup messages. - */ - public static String shortURL(URL u) - { - String s; - if (u == null) - s = "Img null"; - else - { - String file = u.getFile(); - s = u.getHost() + "/.../" + - file.substring(file.lastIndexOf('/') + 1); - } - return s; - } - public String shortURL() - { - return shortURL(purl.url()); - } - - /* return ParsedURL */ - public ParsedURL location() - { - return purl; - } - - /** - * Change alpha values throughout the pixels in the currentRendering. - * Multiply existing alpha by the value passed in. - * This means that transparent areas stay transparent (newAlpha * 0), - * while opaque areas get this level of transparency (newAlpha * 0xff). - * @param scaleFactor TODO - */ - public void scaleAlpha(float scaleFactor) - { - currentRendering.scaleAlpha(scaleFactor); - } - - public int getWidth() - { - return width; - } - - public int getHeight() - { - return height; - } - - public boolean timedOut() - { - return false; - } - public boolean shouldDownloadBiggerVersion() { - /* if originalDimension exists, we scaled the picture down when first downloading it. - so if the user wants to make it bigger than the basisRendering, - we should re-download it and not scale it down */ - return (/* originalDimension != null && */ - width > basisRendering.width || - height > basisRendering.height); - } - - public BufferedImage bufferedImage() - { - return (currentRendering != null) ? currentRendering.bufferedImage : null; - } - - public BufferedImage basisBufferedImage() - { - return basisRendering.bufferedImage; - } - - /** - * Do nothing, but implement Downloadable. - */ - public void handleIoError(Throwable e) - { - // TODO Auto-generated method stub - - } - - /** - * Do nothing, but implement Downloadable. - */ - public boolean isRecycled() - { - // TODO Auto-generated method stub - return false; - } - - /** - * Do nothing, but implement Downloadable. - */ - public void performDownload() throws IOException - { - // TODO Auto-generated method stub - - } - - public BasicSite getSite() - { - return null; - } - - /** - * - * @return What to tell the user about what is being downloaded. - */ - public String message() - { - return "image " + purl; - } - - public void updateRenderings(BufferedImage bufferedImage) - { - if (basisRendering != null) - { - basisRendering.bufferedImage = bufferedImage; - acquirePixelsIfNecessary(); // may have side effects on the bufferedImage we use - bufferedImage = basisRendering.bufferedImage; -// if (unprocessedRendering != null) -// unprocessedRendering. - scaleInitially(width, height, bufferedImage); - restoreAlphaGradient(); - } - } - - public void setWidth(int width) - { - this.width = width; - } - - public void setHeight(int height) - { - this.height = height; - } - - public long getOrmId() - { - return ormId; - } - - public void setOrmId(long ormId) - { - this.ormId = ormId; - } - - public Rendering getBasisRendering() - { - return basisRendering; - } - - public void setBasisRendering(Rendering basisRendering) - { - this.basisRendering = basisRendering; - } - - public Rendering getUnprocessedRendering() - { - return unprocessedRendering; - } - - public void setUnprocessedRendering(Rendering unprocessedRendering) - { - this.unprocessedRendering = unprocessedRendering; - } - - public AlphaGradientRendering getAlphaGradientRendering() - { - if (alphaGradientRendering == null) - alphaGradientRendering = new AlphaGradientRendering(unprocessedRendering, true); - - return alphaGradientRendering; - } - - public void setAlphaGradientRendering(AlphaGradientRendering alphaGradientRendering) - { - this.alphaGradientRendering = alphaGradientRendering; - } - - public BlurredRendering getBlurredRendering() - { - return blurredRendering; - } - - public void setBlurredRendering(BlurredRendering blurredRendering) - { - this.blurredRendering = blurredRendering; - } - - public DesaturatedRendering getDesaturatedRendering() - { - return desaturatedRendering; - } - - public void setDesaturatedRendering(DesaturatedRendering desaturatedRendering) - { - this.desaturatedRendering = desaturatedRendering; - } - - public boolean isScaled() - { - return scaled; - } - - public void setScaled(boolean scaled) - { - this.scaled = scaled; - } - - public Rendering getCurrentRendering() - { - return currentRendering; - } - - - @Override - public boolean isImage() - { - return true; - } - - @Override - public BasicSite getDownloadSite() - { - return null; - } - - @Override - public ParsedURL getDownloadLocation() - { - return location(); - } - - @Override - public boolean isCached() - { - // TODO Auto-generated method stub - return false; - } - - @Override - public DownloadableLogRecord getLogRecord() - { - // TODO Auto-generated method stub - return null; - } - -} +package ecologylab.image; + +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.DirectColorModel; +import java.awt.image.PackedColorModel; +import java.io.IOException; +import java.net.URL; + +import ecologylab.concurrent.BasicSite; +import ecologylab.concurrent.Downloadable; +import ecologylab.concurrent.DownloadableLogRecord; +import ecologylab.concurrent.Site; +import ecologylab.generic.Colors; +import ecologylab.generic.ConsoleUtils; +import ecologylab.generic.MathTools; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_classes; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_wrap; + +/** + * Infrastructure to display, keep track of, and manipulate pixel based media. + * + * Works with {@link Rendering Rendering} to implement pipelined + * image processing transformations on the bits. + */ +@simpl_inherit +public class PixelBased +extends ElementState +implements Downloadable, Colors +{ + + // /////////////////////////// image transform state //////////////////////// + public static final int NO_ALPHA_RADIUS = -1; + + protected static final DirectColorModel ARGB_MODEL = new DirectColorModel(32, 0x00ff0000, 0x0000ff00, 0xff, 0xff000000); + + protected static final PackedColorModel RGB_MODEL = new DirectColorModel(24, 0xff0000, 0xff00, 0xff, 0); + + protected static final int[] ARGB_MASKS = { 0xff0000, 0xff00, 0xff, 0xff000000, }; + + protected static final int[] RGB_MASKS = { 0xff0000, 0xff00, 0xff, }; + + static final int[] RGB_BANDS = { 0, 1, 2 }; + + /** + * Net location of the whatever might get downloaded. Change from URL to ParsedURL. + */ + ParsedURL purl; + + boolean recycled; + + /** + * Don't run grab() more than once. + */ + boolean grabbed; ; + + /** + * like unprocessedRendering, but never part of a chain. image buffer for the completely + * unaltered, the virgin. Usually unscaled, but may be scaled down due to maxDimension, + */ + @simpl_composite + @simpl_classes({ AlphaGradientRendering.class, Rendering.class, DesaturatedRendering.class, BlurredRendering.class }) + @simpl_wrap + Rendering basisRendering; + + /** + * No image processing on this rendering, but if there is scaling to do, this one is scaled. + */ +// @simpl_classes({ AlphaGradientRendering.class, Rendering.class, DesaturatedRendering.class, BlurredRendering.class }) +// @simpl_wrap + protected Rendering unprocessedRendering; + + @simpl_composite + AlphaGradientRendering alphaGradientRendering; + + @simpl_composite + BlurredRendering blurredRendering; + + @simpl_composite + DesaturatedRendering desaturatedRendering; + + /** + * The current Rendering. + */ + @simpl_composite + @simpl_classes({ AlphaGradientRendering.class, Rendering.class, DesaturatedRendering.class, BlurredRendering.class }) + @simpl_wrap + Rendering currentRendering; + + public final Object renderingsLock = new Object(); + + /** + * First Rendering in the pipeline (chain) that is dynamic, that is, that changes after 1st + * rendered. + */ + Rendering firstDynamic; + + private long ormId; + + /** + * Size of the image, once we know it. Position, as well, if its on screen. + */ + // protected Dimension dimension = new Dimension(); + @simpl_scalar + protected int width; + + @simpl_scalar + protected int height; + + // ////////////////////// for debugging //////////////////////////////// + @simpl_scalar + boolean scaled; + + public static int constructedCount, recycledCount; + + public Rendering getFirstDynamic() + { + return firstDynamic; + } + + /////////////////////// constructors ////////////////////////// + public PixelBased() + { + + } + + public PixelBased(BufferedImage bufferedImage) + { + this(bufferedImage, null); + } + public PixelBased(BufferedImage bufferedImage, Dimension maxDimension) + { + if (maxDimension == null) + maxDimension = new Dimension(bufferedImage.getWidth(), bufferedImage.getHeight()); + + Rendering rendering = new Rendering(this, bufferedImage, null, null); + + rendering = scaleRenderingUnderMaxDimension(rendering, rendering.width, rendering.height, maxDimension); + + initializeRenderings(rendering); + + constructedCount++; + } + + public void initializeRenderings(Rendering rendering) + { + width = rendering.width; + height = rendering.height; + basisRendering = rendering; + currentRendering = rendering; + } + + + protected Rendering scaleRenderingUnderMaxDimension(Rendering rendering, + int width, int height, Dimension maxDimension) + { + if( maxDimension!= null ) + { + int maxWidth = maxDimension.width; + int maxHeight = maxDimension.height; + if (width > maxWidth || height > maxHeight) + { + if (width / (float) height < maxWidth / (float) maxHeight) + { + width = (width*maxHeight + height/2) / height; + height = maxHeight; + } + else + { + height = (height*maxWidth + width/2) / width; + width = maxWidth; + } + Rendering origRendering = rendering; + if (width > 0 && height > 0) + { + rendering = rendering.getScaledRendering(width, height); + } + origRendering.recycle(); + origRendering = null; + } + } + return rendering; + } +//////////////////////from regular Image -> int[] pixels ///////////////////// + /** + * If possible, grab the image into memory. This is required for all + * image processing operations. + * This method creates the unprocessed Rendering " + +// newWidth +","+ newHeight); + if (recycled || (basisRendering == null)) + return false; + + if ((bufferedImage.getWidth() != newWidth) || (newHeight != bufferedImage.getHeight())) + { + if (unprocessedRendering == null) + { + synchronized (renderingsLock) + { + width = newWidth; + height = newHeight; + scaled = true; + unprocessedRendering = basisRendering.getScaledRendering(newWidth, newHeight); +// basisRendering = basisRendering.getScaledRendering(newWidth, newHeight); +// unprocessedRendering = new Rendering(basisRendering); + } + } + else + { + //ConsoleUtils.obtrusiveConsoleOutput("Resize in scaleInitially()! " + this + " " + dimension+ + // " ->"+newWidth+","+newHeight); + if ((this.alphaGradientRendering != null) && (this.unprocessedRendering.nextRendering != alphaGradientRendering)) + { + ConsoleUtils.obtrusiveConsoleOutput("GASP! alphaGradient is not in the pipeline chain!"); + } + this.resize(newWidth, newHeight); + if ((this.alphaGradientRendering != null) && (alphaGradientRendering.width != width)) + ConsoleUtils.obtrusiveConsoleOutput("EARLY CRAZY! this="+width+" alphaGrad="+this.alphaGradientRendering.width); + + } + } + else + { + // create new Rendering using the same pixels, DataBufferInt, BufferedImage + // this is efficient! + //ConsoleUtils.obtrusiveConsoleOutput("No Scaling! " + this + " " + dimension); + if (unprocessedRendering == null) + unprocessedRendering = new Rendering(basisRendering); + //unprocessedRendering = unscaledRendering.getScaledRendering(newWidth, newHeight); + } + + this.setCurrentRendering(unprocessedRendering); + return true; + } + public void dontScaleInitially() + { + if (!recycled && (basisRendering != null)) + { + // create new Rendering using the same pixels, DataBufferInt, BufferedImage + // this is efficient! + if (unprocessedRendering == null) + unprocessedRendering = new Rendering(basisRendering); + this.setCurrentRendering(unprocessedRendering); + } + } + public boolean resize(int newWidth, int newHeight) + { + // debug("scale() " + extent.width +","+ extent.height+" -> " + + // newWidth +","+ newHeight); + if (recycled) + return false; + + if ((newWidth != width) || (newHeight != height)) + { + if (unprocessedRendering == null) + { + unprocessedRendering = new Rendering(basisRendering); + this.setCurrentRendering(unprocessedRendering); + } + + synchronized (renderingsLock) + { + width = newWidth; + height = newHeight; + scaled = true; + unprocessedRendering.resize(newWidth, newHeight, basisRendering); +// if (alphaGradientRendering != null) +// { +// unprocessedRendering.computeNext(); +// } + } + } + return true; + } + + public void setupRandomAlphaGradient(float radiusFactor) + { + // now (after probability thresholding), push it up! + radiusFactor = MathTools.bias(radiusFactor, .7f); + int shorter = (width < height) ? width : height; + int alphaRadius = (int) ((shorter / 2) * radiusFactor); + int alphaMinimum = ((int) (MathTools.random(.4f) * (float) R)) & R; + + alphaGradient(alphaRadius, alphaMinimum); + } + /** + * Builds an alpha gradient, or feathered mask. + * + * Acts on buffer in the pixels slot. + * + * @param radius area -- pixels of border to mask + * @param minAlpha lowest alpha setting in mask -- represented in + * red, instead of alpha space, to avoid + * signed arithmetic problems; will shift up later + */ + public boolean alphaGradient(int radius, int minAlpha) + { + if (recycled) + return false; + + if (unprocessedRendering == null) + unprocessedRendering = new Rendering(basisRendering); + + boolean active = (radius != NO_ALPHA_RADIUS); + + if (alphaGradientRendering == null) + alphaGradientRendering = new AlphaGradientRendering(unprocessedRendering, active); + + if (active) + { + alphaGradientRendering.compute(radius, minAlpha); + Rendering last = alphaGradientRendering.lastActive(); + if (last == alphaGradientRendering) + //alphaGradientState.hookup(); + this.setCurrentRendering(alphaGradientRendering); + else + // last.compute(); + alphaGradientRendering.computeNext(); + } + if (alphaGradientRendering.width != width) + ConsoleUtils.obtrusiveConsoleOutput("CRAZY! this="+width+" alphaGrad="+this.alphaGradientRendering.width); + return true; + } + + public boolean alphaGradient(int radius, int minAlpha, int minAlphaInt) + { + alphaGradientRendering.setMinAlphaInt(minAlphaInt); + return alphaGradient(radius, minAlpha); + } + + /** + * @return In alpha gradient blending, the distance from the perimeter, + * inside which opacity is complete. + */ + public double alphaRadius() + { + return (alphaGradientRendering != null) ? alphaGradientRendering.radius : 0; + } + /** + * @return the minimum value opacity mask used for alpha gradient blending. + * [0, 255] + */ + public int minAlpha() + { + return (alphaGradientRendering != null) ? alphaGradientRendering.minAlpha : 0; + } + public boolean hasAlphaGradient() + { + return (alphaGradientRendering != null) && alphaGradientRendering.isActive; + } + public void blur2D(int blurWidth, int blurHeight, boolean immediate) + { + if (recycled || (unprocessedRendering == null)) + return; + synchronized (renderingsLock) + { + if (blurredRendering == null) + { + if (desaturatedRendering == null) + blurredRendering = new BlurredRendering(lastStatic(), true); + else + blurredRendering = new BlurredRendering(lastStatic(), desaturatedRendering, + true); + firstDynamic = blurredRendering; + } + + blurredRendering.compute(blurWidth, blurHeight, false); + blurredRendering.goActive(immediate); + + /* blurState.goActive(); + blurState.compute(blurWidth, blurHeight, immediate); + if (immediate && blurState.isLastActive()) + blurState.hookup(); + */ + } + } + public void noAlphaGradient() + { + this.setCurrentRendering(unprocessedRendering); + unprocessedRendering.recycleRenderingChain(false); + unprocessedRendering.nextRendering = null; + alphaGradientRendering = null; + desaturatedRendering = null; + //goInactive(alphaGradientRendering); + } + public boolean restoreAlphaGradient() + { + boolean result = alphaGradientRendering != null; + if (result) + { + alphaGradientRendering.fixPreviousRendering(unprocessedRendering); // kludge pipeline if necessary + goActive(alphaGradientRendering, true); + } + return result; + } + public void noBlur2D() + { + goInactive(blurredRendering); + } + public void blur2D(float degree, boolean immediate) + { + // for more perceptibly linear response, push degree toward 0 + // degree = MoreMath.bias(degree, .4f); + int blurWidth = (int) ((float) width * .25f * degree); + int blurHeight = (int) ((float) height * .25f * degree); + blur2D(blurWidth, blurHeight, immediate); + } + /** + * @param degree degree of desaturation + */ + public void desaturate(float degree, boolean immediate) + { + if (show(1)) + debug("desaturate("+degree+") " + immediate); + if (recycled || (unprocessedRendering == null)) + return; + if (degree < .07f) + return; + + Rendering blurredRendering = this.blurredRendering; + synchronized (renderingsLock) + { + if (desaturatedRendering == null) + { + if (blurredRendering == null) + { + desaturatedRendering + = new DesaturatedRendering(lastStatic(), true); + // = new DesaturateState(this, alphaGradientState, true); + firstDynamic= desaturatedRendering; + } + else + { + desaturatedRendering + = new DesaturatedRendering(blurredRendering, true); + } + } + if ((blurredRendering != null) && (blurredRendering.previousRendering == null)) + throw new RuntimeException(this + " changed to NULL previousRendering?????);by new DesaturatedRendering"); + + desaturatedRendering.compute(degree); + //desaturatedRendering.goActive(immediate); + setCurrentRendering(desaturatedRendering); + } + } + public void noDesaturate() + { + goInactive(desaturatedRendering); + } + + + /////////////////////// Rendering management ////////////////////////// + void goInactive(Rendering rendering) + { + if (!recycled && (rendering != null)) + rendering.goInactive(); + } + void goActive(Rendering rendering, boolean immediate) + { + if (!recycled && (rendering != null)) + rendering.goActive(immediate); + } + boolean useNoProc; + public void setUseNoProc(boolean value) + { + useNoProc = value; + } + + /////////////////////// Images and MemoryImageSource ////////////////////////// + + public void setCurrentRendering(Rendering rendering) + { + if (!recycled) + this.currentRendering = rendering; + } +////////////////////////sundry services //////////////////////////////// + public Cursor createCustomCursor(Point point, String name) + { + return createCustomCursor(basisRendering.bufferedImage, point, name); + } + + public static Cursor createCustomCursor(BufferedImage bufferedImage, Point point, String name) + { + Toolkit kit = Toolkit.getDefaultToolkit(); + return kit.createCustomCursor(bufferedImage, point, name); + } + +////////////////////////rendering //////////////////////////////// + + Rendering lastStatic() + { + return (alphaGradientRendering == null) ? unprocessedRendering : alphaGradientRendering; + } + /** + * rendering + */ + public void paint(Graphics g, int x, int y) + { + if (!recycled) + { + Rendering rendering = useNoProc ? this.unprocessedRendering : this.currentRendering; + if (rendering != null) + rendering.paint(g, x, y); + //else + //debug("ERROR: trying to render, but no current rendering"); + } + } + public void paint(Graphics2D g2, int x, int y, AffineTransform a) + { + if (!recycled) + { + Rendering rendering = useNoProc ? this.unprocessedRendering : this.currentRendering; + if (rendering != null) + rendering.paint(g2, x, y, a); + //else + //debug("ERROR: trying to render, but no current rendering"); + } + } + +////////////////////////utilities //////////////////////////////// + public String toString() + { + String addr = "["+ ((purl==null) ? "no purl - " + this.getClassSimpleName() : purl.toString())+"]"; + String dim = "[" + width+"x"+height + "] "; + return getClassSimpleName(this) + addr + dim; + } + public String errorMessage() + { + String purlString = (purl == null) ? "null" : purl.toString(); + return "** " + getClassSimpleName() + " can't access content: " + purlString; + } + + public static String hex(int h) + { + return Integer.toHexString(h) + " "; + } + + /** + * Encourage resource relamation -- flush Image and + * release Rendering buffers.. + */ + public void recycle() + { + synchronized (renderingsLock) + { + if (!recycled) + { + //debug("recycle()"); + recycled = true; + + purl = null; + + if (unprocessedRendering != null) + { + unprocessedRendering.recycleRenderingChain(true); + unprocessedRendering.recycle(); // also calls chain of Renderings + unprocessedRendering = null; + } + + if (currentRendering != null) + { + currentRendering.recycle(); + currentRendering = null; + } + + if (firstDynamic != null) + { + firstDynamic.recycle(); + firstDynamic = null; + } + + if (basisRendering != null) + { + basisRendering.recycle(); + basisRendering = null; + } + + if (this.alphaGradientRendering != null) + { + alphaGradientRendering.recycle(); + alphaGradientRendering = null; + } + if (this.desaturatedRendering != null) + { + desaturatedRendering.recycle(); + desaturatedRendering = null; + } + if (this.blurredRendering != null) + { + blurredRendering.recycle(); + blurredRendering = null; + } + recycledCount++; + } + } + } + + /** + * Debugging info about the status of the image. + */ + public String downScaled() + { + String scale= scaled ? " scaled" : ""; + return scale; + } + + /** + * A shorter string for displaing in the modeline for debugging, and + in popup messages. + */ + public static String shortURL(URL u) + { + String s; + if (u == null) + s = "Img null"; + else + { + String file = u.getFile(); + s = u.getHost() + "/.../" + + file.substring(file.lastIndexOf('/') + 1); + } + return s; + } + public String shortURL() + { + return shortURL(purl.url()); + } + + /* return ParsedURL */ + public ParsedURL location() + { + return purl; + } + + /** + * Change alpha values throughout the pixels in the currentRendering. + * Multiply existing alpha by the value passed in. + * This means that transparent areas stay transparent (newAlpha * 0), + * while opaque areas get this level of transparency (newAlpha * 0xff). + * @param scaleFactor TODO + */ + public void scaleAlpha(float scaleFactor) + { + currentRendering.scaleAlpha(scaleFactor); + } + + public int getWidth() + { + return width; + } + + public int getHeight() + { + return height; + } + + public boolean timedOut() + { + return false; + } + public boolean shouldDownloadBiggerVersion() { + /* if originalDimension exists, we scaled the picture down when first downloading it. + so if the user wants to make it bigger than the basisRendering, + we should re-download it and not scale it down */ + return (/* originalDimension != null && */ + width > basisRendering.width || + height > basisRendering.height); + } + + public BufferedImage bufferedImage() + { + return (currentRendering != null) ? currentRendering.bufferedImage : null; + } + + public BufferedImage basisBufferedImage() + { + return basisRendering.bufferedImage; + } + + /** + * Do nothing, but implement Downloadable. + */ + public void handleIoError(Throwable e) + { + // TODO Auto-generated method stub + + } + + /** + * Do nothing, but implement Downloadable. + */ + public boolean isRecycled() + { + // TODO Auto-generated method stub + return false; + } + + /** + * Do nothing, but implement Downloadable. + */ + public void performDownload() throws IOException + { + // TODO Auto-generated method stub + + } + + public Site getSite() + { + return null; + } + + /** + * + * @return What to tell the user about what is being downloaded. + */ + public String message() + { + return "image " + purl; + } + + public void updateRenderings(BufferedImage bufferedImage) + { + if (basisRendering != null) + { + basisRendering.bufferedImage = bufferedImage; + acquirePixelsIfNecessary(); // may have side effects on the bufferedImage we use + bufferedImage = basisRendering.bufferedImage; +// if (unprocessedRendering != null) +// unprocessedRendering. + scaleInitially(width, height, bufferedImage); + restoreAlphaGradient(); + } + } + + public void setWidth(int width) + { + this.width = width; + } + + public void setHeight(int height) + { + this.height = height; + } + + public long getOrmId() + { + return ormId; + } + + public void setOrmId(long ormId) + { + this.ormId = ormId; + } + + public Rendering getBasisRendering() + { + return basisRendering; + } + + public void setBasisRendering(Rendering basisRendering) + { + this.basisRendering = basisRendering; + } + + public Rendering getUnprocessedRendering() + { + return unprocessedRendering; + } + + public void setUnprocessedRendering(Rendering unprocessedRendering) + { + this.unprocessedRendering = unprocessedRendering; + } + + public AlphaGradientRendering getAlphaGradientRendering() + { + if (alphaGradientRendering == null) + alphaGradientRendering = new AlphaGradientRendering(unprocessedRendering, true); + + return alphaGradientRendering; + } + + public void setAlphaGradientRendering(AlphaGradientRendering alphaGradientRendering) + { + this.alphaGradientRendering = alphaGradientRendering; + } + + public BlurredRendering getBlurredRendering() + { + return blurredRendering; + } + + public void setBlurredRendering(BlurredRendering blurredRendering) + { + this.blurredRendering = blurredRendering; + } + + public DesaturatedRendering getDesaturatedRendering() + { + return desaturatedRendering; + } + + public void setDesaturatedRendering(DesaturatedRendering desaturatedRendering) + { + this.desaturatedRendering = desaturatedRendering; + } + + public boolean isScaled() + { + return scaled; + } + + public void setScaled(boolean scaled) + { + this.scaled = scaled; + } + + public Rendering getCurrentRendering() + { + return currentRendering; + } + + + @Override + public boolean isImage() + { + return true; + } + + @Override + public Site getDownloadSite() + { + return null; + } + + @Override + public ParsedURL getDownloadLocation() + { + return location(); + } + + @Override + public boolean isCached() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public DownloadableLogRecord getLogRecord() + { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/image/Rendering.java b/simplSunSpecifics/src/ecologylab/image/Rendering.java similarity index 96% rename from simplPlatformSpecifics/Sun/src/ecologylab/image/Rendering.java rename to simplSunSpecifics/src/ecologylab/image/Rendering.java index b9582586..baa3e7de 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/image/Rendering.java +++ b/simplSunSpecifics/src/ecologylab/image/Rendering.java @@ -1,808 +1,808 @@ -/* - * Copyright 2002 by Texas A&M. - * CONFIDENTIAL. Use is subject to license terms. - */ -package ecologylab.image; - -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import java.awt.image.AffineTransformOp; -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferInt; -import java.awt.image.Raster; -import java.awt.image.SampleModel; -import java.awt.image.SinglePixelPackedSampleModel; -import java.awt.image.WritableRaster; -import java.lang.ref.WeakReference; - -import ecologylab.generic.Colors; -import ecologylab.generic.ImageTools; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_classes; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_wrap; - -/** - * The basic unit of an image processing rendering pipeline; - * Rendering encapsalates a particular graphical state for a - * {@link PixelBased PixelBased} -- either initial state, or a filtered state -- - * and includes references to the next and previous states in the pipeline. - * Thus, these objects form a - * chain of such states that builds a pipeline of image processing operations. - */ -@simpl_inherit -public class Rendering -extends ElementState -implements Colors -{ - /** - * Global count of all pending ImageStates that need to have their pixels recomputed. - */ - static int renderingToDo; - - /** - * Global statistic for debugging memory leaks. - */ - public static int flushCount; - - @simpl_scalar - protected boolean isActive; - - /** - * true if this ImageState needs to have its pixels recomputed. - */ - private boolean isPending; - - /** - * has a non-empty compute op, that gets called periodically, rather than just once for init. - */ - @simpl_scalar - boolean isDynamic; - - /** - * Previous state in the Rendering pipeline. - */ - @simpl_composite - @simpl_classes({ AlphaGradientRendering.class, Rendering.class, DesaturatedRendering.class, BlurredRendering.class }) - @simpl_wrap - Rendering previousRendering; - - /** - * Next state in the Rendering pipeline. - */ - @simpl_composite - @simpl_classes({ AlphaGradientRendering.class, Rendering.class, DesaturatedRendering.class, BlurredRendering.class }) - @simpl_wrap - Rendering nextRendering; - - @simpl_composite - PixelBased pixelBased; - - @simpl_scalar - int width; - - @simpl_scalar - int height; - - /** - * where pixels resulting from this operation live - */ - int[] pixels; - - /** - * DataBuffer that refers to the pixels. - */ - DataBufferInt dataBuffer; - - /** - * BufferedImage that refers to the DataBuffer. - */ - BufferedImage bufferedImage; - - private long ormId; - - public Rendering() - { - - } - - Rendering(PixelBased pixelBased, BufferedImage bufferedImage, DataBufferInt dataBuffer, int[] pixels) - { - this.pixelBased = pixelBased; - this.bufferedImage = bufferedImage; - if (dataBuffer == null) - { - if (bufferedImage.getSampleModel() instanceof SinglePixelPackedSampleModel) - { - Raster raster = bufferedImage.getRaster(); - DataBuffer db = raster.getDataBuffer(); - if (db instanceof DataBufferInt) - { -// debug("EUREKA: Derived dataBuffer and pixels from BufferedImage!"); - dataBuffer = (DataBufferInt) db; - pixels = dataBuffer.getData(); - } - } - } - this.dataBuffer = dataBuffer; - this.pixels = pixels; - this.width = bufferedImage.getWidth(); - this.height = bufferedImage.getHeight(); - this.isActive = true; - } - public Rendering(Rendering mommy) - { - this.pixelBased = mommy.pixelBased; - this.bufferedImage = mommy.bufferedImage; - this.dataBuffer = mommy.dataBuffer; - this.pixels = mommy.pixels; - this.width = mommy.width; - this.height = mommy.height; - this.isActive = true; - } - public Rendering(Rendering previousRendering, boolean active) - { - this.pixelBased = previousRendering.pixelBased; - width = pixelBased.width; - height = pixelBased.height; - isActive = active; - - previousRendering.nextRendering = this; - this.previousRendering = previousRendering; - } - public Rendering(Rendering previousRendering, Rendering nextRendering, - boolean active) - { - this(previousRendering, active); - if (nextRendering != null) - { - nextRendering.previousRendering = this; - this.nextRendering = nextRendering; - } - } - - /** - * If we didnt get a DataBufferInt and pixels when we were constructed, - * copy to get some now. - *

- * If we did, do nothing. - */ - void fixPixels() - { - if ((dataBuffer == null) || (pixels == null)) - { - BufferedImage oldImage = this.bufferedImage; - // create pixels and DataBufferInt, but not WritableRaster and BufferedImage - this.setupImageComponents(oldImage.getWidth(), oldImage.getHeight(), false); - // create new WritableRaster and BufferedImage without flushing the old BufferedImage - // cause we need to copy from it - BufferedImage newImage = createNewBufferedImage(dataBuffer); - this.bufferedImage = newImage; - - debug("fixPixels() copying!! " + pixelBased().location()); - ImageTools.copyImage(oldImage, newImage); - - // now that the copy is done, we can do the flush()! - flush(oldImage); - oldImage = null; - } - } - /** - * @param bImage - */ - private void flush(BufferedImage bImage) - { - bImage.flush(); - new WeakReference(bImage, null); - flushCount++; - } - /** - * Resize what is expected to be a chain. - * - * Use only on noProcStaate -- first in chain. - * Sets up parameters, and clears pixels so it will - * later get recomputed. in forward chained Rendering. - * Then performs a scaling on @param unscaledRendering pixels, and sets - * pixels here to this new, actually scaled pixel array. - * - * For chained states. Sets up parameters, and clears pixels so it will - * later get recomputed. in this and all states.. - */ - void resize(int newWidth, int newHeight, Rendering unscaledRendering) - { - synchronized (pixelBased.renderingsLock) - { - // assumption -- !((newWidth == width) && (newHeight == height)) - - this.resizePipelineImageComponents(newWidth, newHeight); - - ImageTools.scaleAndCopyImage(newWidth, newHeight, - unscaledRendering.bufferedImage, bufferedImage); - - if (nextRendering != null) - nextRendering.compute(this); - - clearPending(); - } - } - /** - * To initially create a scaled version of this Rendering. - * - * @param newWidth - * @param newHeight - * @return - */ - Rendering getScaledRendering(int newWidth, int newHeight) - { - synchronized (pixelBased.renderingsLock) - { - int[] scaledPixels = new int[newWidth * newHeight]; - int size = newWidth * newHeight; - DataBufferInt scaledDataBuffer = new DataBufferInt(scaledPixels, size); - BufferedImage scaledBImage = createNewBufferedImage(scaledDataBuffer, newWidth, newHeight); - - // if you want to clone everything, this is reasonably fast - // even if there's no scaling - ImageTools.scaleAndCopyImage(newWidth, newHeight, bufferedImage, scaledBImage); - - Rendering result = new Rendering(pixelBased, scaledBImage, scaledDataBuffer, scaledPixels); - result.setPreviousRendering(this); -// recycle(); - - return result; - } - } - protected BufferedImage createNewBufferedImage(DataBufferInt scaledDataBuffer, int width, int height) - { - return createNewBufferedImage( scaledDataBuffer, this.bufferedImage, width, height); - } - protected BufferedImage createNewBufferedImage(DataBufferInt scaledDataBuffer) - { - return createNewBufferedImage( scaledDataBuffer, this.bufferedImage, width, height); - } - /** - * Use the DataBuffer passed in, the SampleModel from the current WritableRaster, - * and the ColorModel from the current BufferedImage to create a new BufferedImage. - * - * @param scaledDataBuffer - * @return - */ - protected BufferedImage createNewBufferedImage(DataBufferInt scaledDataBuffer, BufferedImage referenceImage, int width, int height) - { - SampleModel sm = getSampleModel(referenceImage, width, height); - WritableRaster wr = Raster.createWritableRaster(sm, scaledDataBuffer, null); - ColorModel cm = getColorModel(referenceImage); - return new BufferedImage(cm, wr, false, null); - } - protected ColorModel getColorModel(BufferedImage referenceImage) - { - switch(imageType(referenceImage)) - { - case BufferedImage.TYPE_INT_RGB: - return PixelBased.RGB_MODEL; - - case BufferedImage.TYPE_INT_ARGB: - default: - return PixelBased.ARGB_MODEL; - } - } - protected SampleModel getSampleModel(BufferedImage referenceImage, int width, int height) - { - int[] bitMasks; - switch(imageType(referenceImage)) - { - case BufferedImage.TYPE_INT_RGB: - bitMasks = PixelBased.RGB_MASKS; - break; - case BufferedImage.TYPE_INT_ARGB: - default: - bitMasks = PixelBased.ARGB_MASKS; - } - return new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, width, height, bitMasks); - } - private int imageType(BufferedImage referenceImage) - { - return (referenceImage != null) ? referenceImage.getType() : -1; - } - - /* - protected ColorModel getColorModel(BufferedImage referenceImage) - { - return referenceImage.getColorModel(); - } - protected SampleModel getSampleModel(BufferedImage referenceImage) - { - return referenceImage.getSampleModel(); - } - */ - public AffineTransformOp createScaleOp(int newWidth, int newHeight) - { - return createScaleOp(newWidth, newHeight, width, height); - } - public static AffineTransformOp createScaleOp(int newWidth, int newHeight, int oldWidth, int oldHeight) - { - float widthFactor = ((float) newWidth) / ((float) oldWidth); - float heightFactor = ((float) newHeight) / ((float) oldHeight); - - AffineTransform scaleTransform = AffineTransform.getScaleInstance(widthFactor, heightFactor); - AffineTransformOp scaleOp = new AffineTransformOp(scaleTransform, AffineTransformOp.TYPE_BILINEAR); - return scaleOp; - } - protected void resizePipelineImageComponents(int width, int height) - { - resizeImageComponents(width, height, true); - Rendering next = nextRendering; - if (next != null) - next.resizePipelineImageComponents(width, height); - } - protected void setupPipelineImageComponents(int width, int height) - { - setupImageComponents(width, height, true); - Rendering next = nextRendering; - if (next != null) - next.setupPipelineImageComponents(width, height); - } - protected void setupImageComponents(int width, int height) - { - setupImageComponents(width, height, true); - } - protected void resizeImageComponents(int width, int height, boolean createBufferedImage) - { - setupImageComponents(width, height, createBufferedImage); - } - /** - * Create an array of pixels, a DataBufferInt, and a BufferedImage at this size. - * Set our instance variables to refer to these new ones. - *

- * You probably want to save a copy of your reference to any existing BufferedImage - * before calling this, so you can flush() it (after calling this method) when youre ready to. - * @param width - * @param height - * @param createBufferedImage -- If true, create a new BufferedImage, and refer to it. flush() the old one. - */ - protected void setupImageComponents(int width, int height, boolean createBufferedImage) - { - this.width = width; - this.height = height; - int size = width * height; - pixels = new int[size]; - dataBuffer = new DataBufferInt(pixels, size); - if (createBufferedImage) - { - BufferedImage oldImage = this.bufferedImage; - if (oldImage != null) - { - flush(oldImage); - oldImage = null; - this.bufferedImage = null; - } - - BufferedImage newImage = createNewBufferedImage(dataBuffer, width, height); - bufferedImage = newImage; - } - } - public void fill(int pixel) - { - if (pixels == null) - pixels = new int[width*height]; - - fill(pixels, pixel); - print("\t"); - for (int i=(pixels.length-10); i< pixels.length; i++) - print(Integer.toHexString(pixels[i]) + " "); - println(""); - } - public void fill(int[] outPixels, int pixel) - { - for (int i=0; i>= 24; - alpha &= 0xff; - alpha = (int) (scaleFactor * ((float) alpha)); - alpha <<= 24; - } - pixel = alpha | (pixel & RGB); - pixels[i] = pixel; - - } - } - } - - public void setIsActive(boolean isActive) - { - this.isActive = isActive; - } - - public void setWidth(int width) - { - this.width = width; - } - - public void setHeight(int height) - { - this.height = height; - } - - public PixelBased getPixelBased() - { - return pixelBased; - } - - public void setPixelBased(PixelBased pixelBased) - { - this.pixelBased = pixelBased; - } - - public long getOrmId() - { - return ormId; - } - - public void setOrmId(long ormId) - { - this.ormId = ormId; - } - - public boolean getIsDynamic() - { - return isDynamic; - } - - public void setIsDynamic(boolean isDynamic) - { - this.isDynamic = isDynamic; - } - - public Rendering getPreviousRendering() - { - return previousRendering; - } - - public void setPreviousRendering(Rendering previousRendering) - { - this.previousRendering = previousRendering; - } - - public boolean fixPreviousRendering(Rendering newPreviousRendering) - { - boolean result = !this.previousRendering.hasPixels(); - if (result) - { - this.previousRendering = newPreviousRendering; - newPreviousRendering.nextRendering = this; - } - return result; - } - - public Rendering getNextRendering() - { - return nextRendering; - } - - public void setNextRendering(Rendering nextRendering) - { - this.nextRendering = nextRendering; - } - - public boolean getIsActive() - { - return isActive; - } - - public int getWidth() - { - return width; - } - - public int getHeight() - { - return height; - } - public PixelBased pixelBased() - { - PixelBased result = pixelBased; - if (result == null) - { - result = parent(); - this.pixelBased = result; - } - return result; - } - - boolean hasPixels() - { - return pixels != null; - } -} +/* + * Copyright 2002 by Texas A&M. + * CONFIDENTIAL. Use is subject to license terms. + */ +package ecologylab.image; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferInt; +import java.awt.image.Raster; +import java.awt.image.SampleModel; +import java.awt.image.SinglePixelPackedSampleModel; +import java.awt.image.WritableRaster; +import java.lang.ref.WeakReference; + +import ecologylab.generic.Colors; +import ecologylab.generic.ImageTools; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_classes; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_wrap; + +/** + * The basic unit of an image processing rendering pipeline; + * Rendering encapsalates a particular graphical state for a + * {@link PixelBased PixelBased} -- either initial state, or a filtered state -- + * and includes references to the next and previous states in the pipeline. + * Thus, these objects form a + * chain of such states that builds a pipeline of image processing operations. + */ +@simpl_inherit +public class Rendering +extends ElementState +implements Colors +{ + /** + * Global count of all pending ImageStates that need to have their pixels recomputed. + */ + static int renderingToDo; + + /** + * Global statistic for debugging memory leaks. + */ + public static int flushCount; + + @simpl_scalar + protected boolean isActive; + + /** + * true if this ImageState needs to have its pixels recomputed. + */ + private boolean isPending; + + /** + * has a non-empty compute op, that gets called periodically, rather than just once for init. + */ + @simpl_scalar + boolean isDynamic; + + /** + * Previous state in the Rendering pipeline. + */ + @simpl_composite + @simpl_classes({ AlphaGradientRendering.class, Rendering.class, DesaturatedRendering.class, BlurredRendering.class }) + @simpl_wrap + Rendering previousRendering; + + /** + * Next state in the Rendering pipeline. + */ + @simpl_composite + @simpl_classes({ AlphaGradientRendering.class, Rendering.class, DesaturatedRendering.class, BlurredRendering.class }) + @simpl_wrap + Rendering nextRendering; + + @simpl_composite + PixelBased pixelBased; + + @simpl_scalar + int width; + + @simpl_scalar + int height; + + /** + * where pixels resulting from this operation live + */ + int[] pixels; + + /** + * DataBuffer that refers to the pixels. + */ + DataBufferInt dataBuffer; + + /** + * BufferedImage that refers to the DataBuffer. + */ + BufferedImage bufferedImage; + + private long ormId; + + public Rendering() + { + + } + + Rendering(PixelBased pixelBased, BufferedImage bufferedImage, DataBufferInt dataBuffer, int[] pixels) + { + this.pixelBased = pixelBased; + this.bufferedImage = bufferedImage; + if (dataBuffer == null) + { + if (bufferedImage.getSampleModel() instanceof SinglePixelPackedSampleModel) + { + Raster raster = bufferedImage.getRaster(); + DataBuffer db = raster.getDataBuffer(); + if (db instanceof DataBufferInt) + { +// debug("EUREKA: Derived dataBuffer and pixels from BufferedImage!"); + dataBuffer = (DataBufferInt) db; + pixels = dataBuffer.getData(); + } + } + } + this.dataBuffer = dataBuffer; + this.pixels = pixels; + this.width = bufferedImage.getWidth(); + this.height = bufferedImage.getHeight(); + this.isActive = true; + } + public Rendering(Rendering mommy) + { + this.pixelBased = mommy.pixelBased; + this.bufferedImage = mommy.bufferedImage; + this.dataBuffer = mommy.dataBuffer; + this.pixels = mommy.pixels; + this.width = mommy.width; + this.height = mommy.height; + this.isActive = true; + } + public Rendering(Rendering previousRendering, boolean active) + { + this.pixelBased = previousRendering.pixelBased; + width = pixelBased.width; + height = pixelBased.height; + isActive = active; + + previousRendering.nextRendering = this; + this.previousRendering = previousRendering; + } + public Rendering(Rendering previousRendering, Rendering nextRendering, + boolean active) + { + this(previousRendering, active); + if (nextRendering != null) + { + nextRendering.previousRendering = this; + this.nextRendering = nextRendering; + } + } + + /** + * If we didnt get a DataBufferInt and pixels when we were constructed, + * copy to get some now. + *

+ * If we did, do nothing. + */ + void fixPixels() + { + if ((dataBuffer == null) || (pixels == null)) + { + BufferedImage oldImage = this.bufferedImage; + // create pixels and DataBufferInt, but not WritableRaster and BufferedImage + this.setupImageComponents(oldImage.getWidth(), oldImage.getHeight(), false); + // create new WritableRaster and BufferedImage without flushing the old BufferedImage + // cause we need to copy from it + BufferedImage newImage = createNewBufferedImage(dataBuffer); + this.bufferedImage = newImage; + + debug("fixPixels() copying!! " + pixelBased().location()); + ImageTools.copyImage(oldImage, newImage); + + // now that the copy is done, we can do the flush()! + flush(oldImage); + oldImage = null; + } + } + /** + * @param bImage + */ + private void flush(BufferedImage bImage) + { + bImage.flush(); + new WeakReference(bImage, null); + flushCount++; + } + /** + * Resize what is expected to be a chain. + * + * Use only on noProcStaate -- first in chain. + * Sets up parameters, and clears pixels so it will + * later get recomputed. in forward chained Rendering. + * Then performs a scaling on @param unscaledRendering pixels, and sets + * pixels here to this new, actually scaled pixel array. + * + * For chained states. Sets up parameters, and clears pixels so it will + * later get recomputed. in this and all states.. + */ + void resize(int newWidth, int newHeight, Rendering unscaledRendering) + { + synchronized (pixelBased.renderingsLock) + { + // assumption -- !((newWidth == width) && (newHeight == height)) + + this.resizePipelineImageComponents(newWidth, newHeight); + + ImageTools.scaleAndCopyImage(newWidth, newHeight, + unscaledRendering.bufferedImage, bufferedImage); + + if (nextRendering != null) + nextRendering.compute(this); + + clearPending(); + } + } + /** + * To initially create a scaled version of this Rendering. + * + * @param newWidth + * @param newHeight + * @return + */ + Rendering getScaledRendering(int newWidth, int newHeight) + { + synchronized (pixelBased.renderingsLock) + { + int[] scaledPixels = new int[newWidth * newHeight]; + int size = newWidth * newHeight; + DataBufferInt scaledDataBuffer = new DataBufferInt(scaledPixels, size); + BufferedImage scaledBImage = createNewBufferedImage(scaledDataBuffer, newWidth, newHeight); + + // if you want to clone everything, this is reasonably fast + // even if there's no scaling + ImageTools.scaleAndCopyImage(newWidth, newHeight, bufferedImage, scaledBImage); + + Rendering result = new Rendering(pixelBased, scaledBImage, scaledDataBuffer, scaledPixels); + result.setPreviousRendering(this); +// recycle(); + + return result; + } + } + protected BufferedImage createNewBufferedImage(DataBufferInt scaledDataBuffer, int width, int height) + { + return createNewBufferedImage( scaledDataBuffer, this.bufferedImage, width, height); + } + protected BufferedImage createNewBufferedImage(DataBufferInt scaledDataBuffer) + { + return createNewBufferedImage( scaledDataBuffer, this.bufferedImage, width, height); + } + /** + * Use the DataBuffer passed in, the SampleModel from the current WritableRaster, + * and the ColorModel from the current BufferedImage to create a new BufferedImage. + * + * @param scaledDataBuffer + * @return + */ + protected BufferedImage createNewBufferedImage(DataBufferInt scaledDataBuffer, BufferedImage referenceImage, int width, int height) + { + SampleModel sm = getSampleModel(referenceImage, width, height); + WritableRaster wr = Raster.createWritableRaster(sm, scaledDataBuffer, null); + ColorModel cm = getColorModel(referenceImage); + return new BufferedImage(cm, wr, false, null); + } + protected ColorModel getColorModel(BufferedImage referenceImage) + { + switch(imageType(referenceImage)) + { + case BufferedImage.TYPE_INT_RGB: + return PixelBased.RGB_MODEL; + + case BufferedImage.TYPE_INT_ARGB: + default: + return PixelBased.ARGB_MODEL; + } + } + protected SampleModel getSampleModel(BufferedImage referenceImage, int width, int height) + { + int[] bitMasks; + switch(imageType(referenceImage)) + { + case BufferedImage.TYPE_INT_RGB: + bitMasks = PixelBased.RGB_MASKS; + break; + case BufferedImage.TYPE_INT_ARGB: + default: + bitMasks = PixelBased.ARGB_MASKS; + } + return new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, width, height, bitMasks); + } + private int imageType(BufferedImage referenceImage) + { + return (referenceImage != null) ? referenceImage.getType() : -1; + } + + /* + protected ColorModel getColorModel(BufferedImage referenceImage) + { + return referenceImage.getColorModel(); + } + protected SampleModel getSampleModel(BufferedImage referenceImage) + { + return referenceImage.getSampleModel(); + } + */ + public AffineTransformOp createScaleOp(int newWidth, int newHeight) + { + return createScaleOp(newWidth, newHeight, width, height); + } + public static AffineTransformOp createScaleOp(int newWidth, int newHeight, int oldWidth, int oldHeight) + { + float widthFactor = ((float) newWidth) / ((float) oldWidth); + float heightFactor = ((float) newHeight) / ((float) oldHeight); + + AffineTransform scaleTransform = AffineTransform.getScaleInstance(widthFactor, heightFactor); + AffineTransformOp scaleOp = new AffineTransformOp(scaleTransform, AffineTransformOp.TYPE_BILINEAR); + return scaleOp; + } + protected void resizePipelineImageComponents(int width, int height) + { + resizeImageComponents(width, height, true); + Rendering next = nextRendering; + if (next != null) + next.resizePipelineImageComponents(width, height); + } + protected void setupPipelineImageComponents(int width, int height) + { + setupImageComponents(width, height, true); + Rendering next = nextRendering; + if (next != null) + next.setupPipelineImageComponents(width, height); + } + protected void setupImageComponents(int width, int height) + { + setupImageComponents(width, height, true); + } + protected void resizeImageComponents(int width, int height, boolean createBufferedImage) + { + setupImageComponents(width, height, createBufferedImage); + } + /** + * Create an array of pixels, a DataBufferInt, and a BufferedImage at this size. + * Set our instance variables to refer to these new ones. + *

+ * You probably want to save a copy of your reference to any existing BufferedImage + * before calling this, so you can flush() it (after calling this method) when youre ready to. + * @param width + * @param height + * @param createBufferedImage -- If true, create a new BufferedImage, and refer to it. flush() the old one. + */ + protected void setupImageComponents(int width, int height, boolean createBufferedImage) + { + this.width = width; + this.height = height; + int size = width * height; + pixels = new int[size]; + dataBuffer = new DataBufferInt(pixels, size); + if (createBufferedImage) + { + BufferedImage oldImage = this.bufferedImage; + if (oldImage != null) + { + flush(oldImage); + oldImage = null; + this.bufferedImage = null; + } + + BufferedImage newImage = createNewBufferedImage(dataBuffer, width, height); + bufferedImage = newImage; + } + } + public void fill(int pixel) + { + if (pixels == null) + pixels = new int[width*height]; + + fill(pixels, pixel); + print("\t"); + for (int i=(pixels.length-10); i< pixels.length; i++) + print(Integer.toHexString(pixels[i]) + " "); + println(""); + } + public void fill(int[] outPixels, int pixel) + { + for (int i=0; i>= 24; + alpha &= 0xff; + alpha = (int) (scaleFactor * ((float) alpha)); + alpha <<= 24; + } + pixel = alpha | (pixel & RGB); + pixels[i] = pixel; + + } + } + } + + public void setIsActive(boolean isActive) + { + this.isActive = isActive; + } + + public void setWidth(int width) + { + this.width = width; + } + + public void setHeight(int height) + { + this.height = height; + } + + public PixelBased getPixelBased() + { + return pixelBased; + } + + public void setPixelBased(PixelBased pixelBased) + { + this.pixelBased = pixelBased; + } + + public long getOrmId() + { + return ormId; + } + + public void setOrmId(long ormId) + { + this.ormId = ormId; + } + + public boolean getIsDynamic() + { + return isDynamic; + } + + public void setIsDynamic(boolean isDynamic) + { + this.isDynamic = isDynamic; + } + + public Rendering getPreviousRendering() + { + return previousRendering; + } + + public void setPreviousRendering(Rendering previousRendering) + { + this.previousRendering = previousRendering; + } + + public boolean fixPreviousRendering(Rendering newPreviousRendering) + { + boolean result = !this.previousRendering.hasPixels(); + if (result) + { + this.previousRendering = newPreviousRendering; + newPreviousRendering.nextRendering = this; + } + return result; + } + + public Rendering getNextRendering() + { + return nextRendering; + } + + public void setNextRendering(Rendering nextRendering) + { + this.nextRendering = nextRendering; + } + + public boolean getIsActive() + { + return isActive; + } + + public int getWidth() + { + return width; + } + + public int getHeight() + { + return height; + } + public PixelBased pixelBased() + { + PixelBased result = pixelBased; + if (result == null) + { + result = parent(); + this.pixelBased = result; + } + return result; + } + + boolean hasPixels() + { + return pixels != null; + } +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/image/package.html b/simplSunSpecifics/src/ecologylab/image/package.html similarity index 96% rename from simplPlatformSpecifics/Sun/src/ecologylab/image/package.html rename to simplSunSpecifics/src/ecologylab/image/package.html index cd9266fe..37f5bbd1 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/image/package.html +++ b/simplSunSpecifics/src/ecologylab/image/package.html @@ -1,4 +1,4 @@ - -Application independent functionalities for downloading and -manipulating media such as images and sounds. - + +Application independent functionalities for downloading and +manipulating media such as images and sounds. + diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/platformspecifics/FundamentalPlatformSpecificsSun.java b/simplSunSpecifics/src/ecologylab/platformspecifics/FundamentalPlatformSpecificsSun.java similarity index 100% rename from simplPlatformSpecifics/Sun/src/ecologylab/platformspecifics/FundamentalPlatformSpecificsSun.java rename to simplSunSpecifics/src/ecologylab/platformspecifics/FundamentalPlatformSpecificsSun.java diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLParserSun.java b/simplSunSpecifics/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLParserSun.java similarity index 100% rename from simplPlatformSpecifics/Sun/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLParserSun.java rename to simplSunSpecifics/src/ecologylab/serialization/deserializers/pullhandlers/stringformats/XMLParserSun.java diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/PlatformSpecificTypesSun.java b/simplSunSpecifics/src/ecologylab/serialization/types/PlatformSpecificTypesSun.java similarity index 96% rename from simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/PlatformSpecificTypesSun.java rename to simplSunSpecifics/src/ecologylab/serialization/types/PlatformSpecificTypesSun.java index 00292e0c..c63d7e92 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/PlatformSpecificTypesSun.java +++ b/simplSunSpecifics/src/ecologylab/serialization/types/PlatformSpecificTypesSun.java @@ -1,28 +1,28 @@ -/** - * - */ -package ecologylab.serialization.types; - -import ecologylab.generic.Debug; -import ecologylab.serialization.types.scalar.BufferedImageType; -import ecologylab.serialization.types.scalar.ColorType; -import ecologylab.serialization.types.scalar.AwtImageType; -import ecologylab.serialization.types.scalar.RectangleType; - -/** - * This class initializes ScalarTypes that depend on java.awt.*, which does not exist in Android. - * - * @author andruid - */ -public class PlatformSpecificTypesSun extends Debug -{ - public static final ScalarType COLOR_TYPE = new ColorType(); - - public static final ScalarType RECTANGLE_TYPE = new RectangleType(); - - public static final ScalarType IMAGE_TYPE = new AwtImageType(); - - public static final ScalarType BUFFERED_IMAGE_TYPE = new BufferedImageType(); - - -} +/** + * + */ +package ecologylab.serialization.types; + +import ecologylab.generic.Debug; +import ecologylab.serialization.types.scalar.BufferedImageType; +import ecologylab.serialization.types.scalar.ColorType; +import ecologylab.serialization.types.scalar.AwtImageType; +import ecologylab.serialization.types.scalar.RectangleType; + +/** + * This class initializes ScalarTypes that depend on java.awt.*, which does not exist in Android. + * + * @author andruid + */ +public class PlatformSpecificTypesSun extends Debug +{ + public static final ScalarType COLOR_TYPE = new ColorType(); + + public static final ScalarType RECTANGLE_TYPE = new RectangleType(); + + public static final ScalarType IMAGE_TYPE = new AwtImageType(); + + public static final ScalarType BUFFERED_IMAGE_TYPE = new BufferedImageType(); + + +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/scalar/AwtImageType.java b/simplSunSpecifics/src/ecologylab/serialization/types/scalar/AwtImageType.java similarity index 96% rename from simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/scalar/AwtImageType.java rename to simplSunSpecifics/src/ecologylab/serialization/types/scalar/AwtImageType.java index 13020cfa..c72e77b2 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/scalar/AwtImageType.java +++ b/simplSunSpecifics/src/ecologylab/serialization/types/scalar/AwtImageType.java @@ -1,107 +1,107 @@ -/******************************************************************************* - * Revision History:
- * SRL Member - File created - * - *

- * - *

- *  This work is released under the BSD License:
- *  (C) 2011 Sketch Recognition Lab, Texas A&M University (hereafter SRL @ TAMU)
- *  All rights reserved.
- * 
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are met:
- *      * Redistributions of source code must retain the above copyright
- *        notice, this list of conditions and the following disclaimer.
- *      * Redistributions in binary form must reproduce the above copyright
- *        notice, this list of conditions and the following disclaimer in the
- *        documentation and/or other materials provided with the distribution.
- *      * Neither the name of the Sketch Recognition Lab, Texas A&M University 
- *        nor the names of its contributors may be used to endorse or promote 
- *        products derived from this software without specific prior written 
- *        permission.
- *  
- *  THIS SOFTWARE IS PROVIDED BY SRL @ TAMU ``AS IS'' AND ANY
- *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL SRL @ TAMU BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * 
- * - *******************************************************************************/ -package ecologylab.serialization.types.scalar; - -import java.awt.Image; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import javax.imageio.ImageIO; - -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; - -public class AwtImageType extends ImageType -{ - - public AwtImageType() - { - this(Image.class); - } - - protected AwtImageType(Class thatClass) - { - super(thatClass); - } - - @Override - public I getInstance(String value, String[] formatStrings, - ScalarUnmarshallingContext scalarUnmarshallingContext) - { - - byte[] data = stringToByteArray(value); - - try - { - return (I) ImageIO.read(new ByteArrayInputStream(data)); - } - catch (IOException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - return null; - } - - @Override - public String marshall(I i, TranslationContext suc) - { - try - { - BufferedImage img = (BufferedImage) i; - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ImageIO.write(img, "png", baos); - - return byteArrayToString(baos.toByteArray()); - } - catch (IOException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - catch (ClassCastException e) - { - e.printStackTrace(); - } - - return null; - } - -} +/******************************************************************************* + * Revision History:
+ * SRL Member - File created + * + *

+ * + *

+ *  This work is released under the BSD License:
+ *  (C) 2011 Sketch Recognition Lab, Texas A&M University (hereafter SRL @ TAMU)
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *      * Redistributions of source code must retain the above copyright
+ *        notice, this list of conditions and the following disclaimer.
+ *      * Redistributions in binary form must reproduce the above copyright
+ *        notice, this list of conditions and the following disclaimer in the
+ *        documentation and/or other materials provided with the distribution.
+ *      * Neither the name of the Sketch Recognition Lab, Texas A&M University 
+ *        nor the names of its contributors may be used to endorse or promote 
+ *        products derived from this software without specific prior written 
+ *        permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY SRL @ TAMU ``AS IS'' AND ANY
+ *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL SRL @ TAMU BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * + *******************************************************************************/ +package ecologylab.serialization.types.scalar; + +import java.awt.Image; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; + +public class AwtImageType extends ImageType +{ + + public AwtImageType() + { + this(Image.class); + } + + protected AwtImageType(Class thatClass) + { + super(thatClass); + } + + @Override + public I getInstance(String value, String[] formatStrings, + ScalarUnmarshallingContext scalarUnmarshallingContext) + { + + byte[] data = stringToByteArray(value); + + try + { + return (I) ImageIO.read(new ByteArrayInputStream(data)); + } + catch (IOException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return null; + } + + @Override + public String marshall(I i, TranslationContext suc) + { + try + { + BufferedImage img = (BufferedImage) i; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(img, "png", baos); + + return byteArrayToString(baos.toByteArray()); + } + catch (IOException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + catch (ClassCastException e) + { + e.printStackTrace(); + } + + return null; + } + +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/scalar/BufferedImageType.java b/simplSunSpecifics/src/ecologylab/serialization/types/scalar/BufferedImageType.java similarity index 97% rename from simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/scalar/BufferedImageType.java rename to simplSunSpecifics/src/ecologylab/serialization/types/scalar/BufferedImageType.java index 56e597e5..9355f9d4 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/scalar/BufferedImageType.java +++ b/simplSunSpecifics/src/ecologylab/serialization/types/scalar/BufferedImageType.java @@ -1,48 +1,48 @@ -/******************************************************************************* - * Revision History:
- * SRL Member - File created - * - *

- * - *

- *  This work is released under the BSD License:
- *  (C) 2011 Sketch Recognition Lab, Texas A&M University (hereafter SRL @ TAMU)
- *  All rights reserved.
- * 
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are met:
- *      * Redistributions of source code must retain the above copyright
- *        notice, this list of conditions and the following disclaimer.
- *      * Redistributions in binary form must reproduce the above copyright
- *        notice, this list of conditions and the following disclaimer in the
- *        documentation and/or other materials provided with the distribution.
- *      * Neither the name of the Sketch Recognition Lab, Texas A&M University 
- *        nor the names of its contributors may be used to endorse or promote 
- *        products derived from this software without specific prior written 
- *        permission.
- *  
- *  THIS SOFTWARE IS PROVIDED BY SRL @ TAMU ``AS IS'' AND ANY
- *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL SRL @ TAMU BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * 
- * - *******************************************************************************/ -package ecologylab.serialization.types.scalar; - -import java.awt.image.BufferedImage; - -public class BufferedImageType extends AwtImageType -{ - - public BufferedImageType() - { - super(BufferedImage.class); - } - -} +/******************************************************************************* + * Revision History:
+ * SRL Member - File created + * + *

+ * + *

+ *  This work is released under the BSD License:
+ *  (C) 2011 Sketch Recognition Lab, Texas A&M University (hereafter SRL @ TAMU)
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *      * Redistributions of source code must retain the above copyright
+ *        notice, this list of conditions and the following disclaimer.
+ *      * Redistributions in binary form must reproduce the above copyright
+ *        notice, this list of conditions and the following disclaimer in the
+ *        documentation and/or other materials provided with the distribution.
+ *      * Neither the name of the Sketch Recognition Lab, Texas A&M University 
+ *        nor the names of its contributors may be used to endorse or promote 
+ *        products derived from this software without specific prior written 
+ *        permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY SRL @ TAMU ``AS IS'' AND ANY
+ *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL SRL @ TAMU BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * + *******************************************************************************/ +package ecologylab.serialization.types.scalar; + +import java.awt.image.BufferedImage; + +public class BufferedImageType extends AwtImageType +{ + + public BufferedImageType() + { + super(BufferedImage.class); + } + +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/scalar/ColorType.java b/simplSunSpecifics/src/ecologylab/serialization/types/scalar/ColorType.java similarity index 96% rename from simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/scalar/ColorType.java rename to simplSunSpecifics/src/ecologylab/serialization/types/scalar/ColorType.java index cdc1f257..ff48dbfc 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/scalar/ColorType.java +++ b/simplSunSpecifics/src/ecologylab/serialization/types/scalar/ColorType.java @@ -1,75 +1,75 @@ -/* - * Created on Dec 31, 2004 at the Interface Ecology Lab. - */ -package ecologylab.serialization.types.scalar; - -import java.awt.Color; - -import ecologylab.serialization.ScalarUnmarshallingContext; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.types.CrossLanguageTypeConstants; -import ecologylab.serialization.types.ScalarType; - -/** - * Type system entry for java.awt.Color. Uses a hex string as initialization. - * - * @author andruid - */ -@simpl_inherit -public class ColorType extends ScalarType -implements CrossLanguageTypeConstants -{ -/** - * This constructor should only be called once per session, through - * a static initializer, typically in TypeRegistry. - *

- * To get the instance of this type object for use in translations, call - * TypeRegistry.get("java.awt.Color"). - * - */ - public ColorType() - { - super(Color.class, DOTNET_COLOR, OBJC_COLOR, null); - } - - /** - * @param value is interpreted as hex-encoded RGB value, in the - * same style as HTML & CSS. A # character at the start is unneccesary, - * but acceptable. - * - * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], ScalarUnmarshallingContext) - */ - public Color getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) - { - if (value.indexOf('#') == 0) - value = value.substring(1); - - // we *should* be able to use int and parseInt() here, but - // apparently, there's a bug in the JDK, so we use long - // and then cast down - long argb = Long.parseLong(value, 16); - boolean hasAlpha = (argb >= 0x01000000); - return new Color((int) argb, hasAlpha); - } - - /** - * Get a String representation of the instance, using this. - * The default just calls the toString() method on the instance. - * @param color - * @return - */ - @Override - public String marshall(Color color, TranslationContext serializationContext) - { - String result; - int argb = color.getRGB(); - int alpha = argb & 0xff000000; - if (alpha == 0xff000000) - argb = argb & 0xffffff; -// debugA("rgba="+Integer.toHexString(argb)+" alpha="+alpha); - result = Integer.toHexString(argb); - return '#' + result; - } - -} +/* + * Created on Dec 31, 2004 at the Interface Ecology Lab. + */ +package ecologylab.serialization.types.scalar; + +import java.awt.Color; + +import ecologylab.serialization.ScalarUnmarshallingContext; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.types.CrossLanguageTypeConstants; +import ecologylab.serialization.types.ScalarType; + +/** + * Type system entry for java.awt.Color. Uses a hex string as initialization. + * + * @author andruid + */ +@simpl_inherit +public class ColorType extends ScalarType +implements CrossLanguageTypeConstants +{ +/** + * This constructor should only be called once per session, through + * a static initializer, typically in TypeRegistry. + *

+ * To get the instance of this type object for use in translations, call + * TypeRegistry.get("java.awt.Color"). + * + */ + public ColorType() + { + super(Color.class, DOTNET_COLOR, OBJC_COLOR, null); + } + + /** + * @param value is interpreted as hex-encoded RGB value, in the + * same style as HTML & CSS. A # character at the start is unneccesary, + * but acceptable. + * + * @see ecologylab.serialization.types.ScalarType#getInstance(java.lang.String, String[], ScalarUnmarshallingContext) + */ + public Color getInstance(String value, String[] formatStrings, ScalarUnmarshallingContext scalarUnmarshallingContext) + { + if (value.indexOf('#') == 0) + value = value.substring(1); + + // we *should* be able to use int and parseInt() here, but + // apparently, there's a bug in the JDK, so we use long + // and then cast down + long argb = Long.parseLong(value, 16); + boolean hasAlpha = (argb >= 0x01000000); + return new Color((int) argb, hasAlpha); + } + + /** + * Get a String representation of the instance, using this. + * The default just calls the toString() method on the instance. + * @param color + * @return + */ + @Override + public String marshall(Color color, TranslationContext serializationContext) + { + String result; + int argb = color.getRGB(); + int alpha = argb & 0xff000000; + if (alpha == 0xff000000) + argb = argb & 0xffffff; +// debugA("rgba="+Integer.toHexString(argb)+" alpha="+alpha); + result = Integer.toHexString(argb); + return '#' + result; + } + +} diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/scalar/RectangleType.java b/simplSunSpecifics/src/ecologylab/serialization/types/scalar/RectangleType.java similarity index 100% rename from simplPlatformSpecifics/Sun/src/ecologylab/serialization/types/scalar/RectangleType.java rename to simplSunSpecifics/src/ecologylab/serialization/types/scalar/RectangleType.java diff --git a/simplPlatformSpecifics/Sun/src/ecologylab/standalone/PrefsEditorAp.java b/simplSunSpecifics/src/ecologylab/standalone/PrefsEditorAp.java similarity index 96% rename from simplPlatformSpecifics/Sun/src/ecologylab/standalone/PrefsEditorAp.java rename to simplSunSpecifics/src/ecologylab/standalone/PrefsEditorAp.java index 258b35aa..1e56dc15 100644 --- a/simplPlatformSpecifics/Sun/src/ecologylab/standalone/PrefsEditorAp.java +++ b/simplSunSpecifics/src/ecologylab/standalone/PrefsEditorAp.java @@ -1,36 +1,36 @@ -/** - * - */ -package ecologylab.standalone; - -import ecologylab.appframework.SingletonApplicationEnvironment; -import ecologylab.appframework.types.prefs.PrefsTranslationsProvider; -import ecologylab.appframework.types.prefs.gui.PrefsEditor; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; - -/** - * Standalone app to open a prefs editing dialog. - * - * @author Cae - * @author andruid - */ -public class PrefsEditorAp extends SingletonApplicationEnvironment -{ - - public PrefsEditorAp(String[] args) throws SIMPLTranslationException - { - super("ecologyLabFundamental", PrefsTranslationsProvider.get(), (SimplTypesScope) null, args, 0); - - this.createPrefsEditor(true, true); - } - /** - * @param args - * @throws SIMPLTranslationException - */ - public static void main(String[] args) throws SIMPLTranslationException - { - new PrefsEditorAp(args); - } - -} +/** + * + */ +package ecologylab.standalone; + +import ecologylab.appframework.SingletonApplicationEnvironment; +import ecologylab.appframework.types.prefs.PrefsTranslationsProvider; +import ecologylab.appframework.types.prefs.gui.PrefsEditor; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; + +/** + * Standalone app to open a prefs editing dialog. + * + * @author Cae + * @author andruid + */ +public class PrefsEditorAp extends SingletonApplicationEnvironment +{ + + public PrefsEditorAp(String[] args) throws SIMPLTranslationException + { + super("ecologyLabFundamental", PrefsTranslationsProvider.get(), (SimplTypesScope) null, args, 0); + + this.createPrefsEditor(true, true); + } + /** + * @param args + * @throws SIMPLTranslationException + */ + public static void main(String[] args) throws SIMPLTranslationException + { + new PrefsEditorAp(args); + } + +} diff --git a/simplTests/.classpath b/simplTests/.classpath index 74117f6d..8792e67c 100644 --- a/simplTests/.classpath +++ b/simplTests/.classpath @@ -1,11 +1,12 @@ - - - - - - - - - - - + + + + + + + + + + + + diff --git a/simplTests/.project b/simplTests/.project index 14bc2dce..99713f28 100644 --- a/simplTests/.project +++ b/simplTests/.project @@ -1,17 +1,17 @@ - - - simplTests - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - + + + simplTests + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/simplTests/test/ecologylab/collections/TestFilteredIterator.java b/simplTests/test/ecologylab/collections/TestFilteredIterator.java new file mode 100644 index 00000000..85e5ac7d --- /dev/null +++ b/simplTests/test/ecologylab/collections/TestFilteredIterator.java @@ -0,0 +1,56 @@ +package ecologylab.collections; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Iterator; +import java.util.List; + +import org.junit.Test; + +import com.google.common.primitives.Ints; + +public class TestFilteredIterator +{ + + @Test + public void test() + { + int[] a = { 1, 2, 3, 4, 5, 6 }; + List s = Ints.asList(a); + + FilteredIterator fi1 = new FilteredIterator(s.iterator()) + { + @Override + protected boolean keepElement(Integer element) + { + return element % 2 == 0; + } + }; + assertTrue(fi1.hasNext()); + assertEquals(2, fi1.next().intValue()); + assertTrue(fi1.hasNext()); + assertEquals(4, fi1.next().intValue()); + assertTrue(fi1.hasNext()); + assertEquals(6, fi1.next().intValue()); + assertFalse(fi1.hasNext()); + + FilteredIterator fi2 = new FilteredIterator(s.iterator()) + { + @Override + protected boolean keepElement(Integer element) + { + return element % 2 == 1; + } + }; + assertTrue(fi2.hasNext()); + assertEquals(1, fi2.next().intValue()); + assertTrue(fi2.hasNext()); + assertEquals(3, fi2.next().intValue()); + assertTrue(fi2.hasNext()); + assertEquals(5, fi2.next().intValue()); + assertFalse(fi2.hasNext()); + } + +} diff --git a/simplTests/test/ecologylab/concurrent/DownloadMonitorMemoryTester.java b/simplTests/test/ecologylab/concurrent/DownloadMonitorMemoryTester.java new file mode 100644 index 00000000..1ea4acaf --- /dev/null +++ b/simplTests/test/ecologylab/concurrent/DownloadMonitorMemoryTester.java @@ -0,0 +1,135 @@ +package ecologylab.concurrent; + +import java.io.IOException; +import java.util.Random; + +import ecologylab.generic.Continuation; +import ecologylab.net.ParsedURL; + +/** + * Run fake tasks through DownloadMonitor to check for problems. + * + * @author quyin + */ +public class DownloadMonitorMemoryTester +{ + + static String CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz "; + + static Random r = new Random(); + + static class Task implements Downloadable + { + + ParsedURL location; + + char[] buf; + + public Task(ParsedURL location) + { + this.location = location; + } + + @Override + public void performDownload() throws IOException + { + buf = new char[10 * 1024 * 1024]; + for (int i = 0; i < buf.length; ++i) + { + buf[i] = CHARS.charAt(r.nextInt(CHARS.length())); + } + } + + @Override + public void handleIoError(Throwable e) + { + System.err.println(e); + } + + @Override + public boolean isRecycled() + { + return false; + } + + @Override + public void recycle() + { + } + + @Override + public Site getSite() + { + return null; + } + + @Override + public Site getDownloadSite() + { + return null; + } + + @Override + public ParsedURL location() + { + return location; + } + + @Override + public ParsedURL getDownloadLocation() + { + return location; + } + + @Override + public boolean isImage() + { + return false; + } + + @Override + public String message() + { + return null; + } + + @Override + public boolean isCached() + { + return false; + } + + @Override + public DownloadableLogRecord getLogRecord() + { + return null; + } + + } + + public void runFakeTasks() + { + DownloadMonitor dm = new DownloadMonitor("test", 2); + for (int i = 0; i < 10; ++i) + { + dm.download(new Task(ParsedURL.getAbsolute("http://example.com/pages/" + i)), + new Continuation() + { + @Override + public void callback(Task o) + { + System.out.println(o.location() + " downloaded."); + } + }); + } + dm.requestStop(); + } + + public static void main(String[] args) + { + System.out.println("Run this program with heap size <=100M (-Xms100m -Xmx100m)."); + DownloadMonitorMemoryTester dmt = new DownloadMonitorMemoryTester(); + dmt.runFakeTasks(); + } + +} diff --git a/simplTests/test/ecologylab/concurrent/FakeDownloadable.java b/simplTests/test/ecologylab/concurrent/FakeDownloadable.java new file mode 100644 index 00000000..b63bf2f6 --- /dev/null +++ b/simplTests/test/ecologylab/concurrent/FakeDownloadable.java @@ -0,0 +1,120 @@ +package ecologylab.concurrent; + +import java.io.IOException; + +import ecologylab.net.ParsedURL; + +/** + * For test. + * + * @author quyin + */ +public class FakeDownloadable implements Downloadable +{ + + ParsedURL location; + + ParsedURL downloadLocation; + + boolean isImage; + + boolean isCached; + + boolean downloaded = false; + + DownloadableLogRecord logRecord = new DownloadableLogRecord(); + + public FakeDownloadable(ParsedURL location) + { + this(location, location, false, false); + } + + public FakeDownloadable(ParsedURL location, + ParsedURL downloadLocation, + boolean isImage, + boolean isCached) + { + this.location = location; + this.downloadLocation = downloadLocation; + this.isImage = isImage; + } + + @Override + public void performDownload() throws IOException + { + downloaded = true; + } + + @Override + public void handleIoError(Throwable e) + { + throw new RuntimeException("I/O error while downloading", e); + } + + @Override + public boolean isRecycled() + { + return false; + } + + @Override + public void recycle() + { + // no-op + } + + /** + * Subclass can override this to return a fake site object. + */ + @Override + public Site getSite() + { + return null; + } + + /** + * Subclass can override this to return a fake site object. + */ + @Override + public Site getDownloadSite() + { + return null; + } + + @Override + public ParsedURL location() + { + return location; + } + + @Override + public ParsedURL getDownloadLocation() + { + return downloadLocation; + } + + @Override + public boolean isImage() + { + return isImage; + } + + @Override + public String message() + { + return getClass().getSimpleName() + "[" + location.toString() + "]"; + } + + @Override + public boolean isCached() + { + return isCached; + } + + @Override + public DownloadableLogRecord getLogRecord() + { + return logRecord; + } + +} diff --git a/simplTests/test/ecologylab/concurrent/TestDownloadMonitor.java b/simplTests/test/ecologylab/concurrent/TestDownloadMonitor.java new file mode 100644 index 00000000..d1754e7b --- /dev/null +++ b/simplTests/test/ecologylab/concurrent/TestDownloadMonitor.java @@ -0,0 +1,48 @@ +package ecologylab.concurrent; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.concurrent.ExecutionException; + +import org.junit.Before; +import org.junit.Test; + +import ecologylab.logging.LogEvent; +import ecologylab.logging.LogPost; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.StringFormat; + +public class TestDownloadMonitor +{ + + DownloadMonitor dm; + + @Before + public void setup() + { + dm = new DownloadMonitor("test-dm", 3); + } + + @Test + public void testLogEvents() throws InterruptedException, ExecutionException + { + FakeDownloadable d = new FakeDownloadable(ParsedURL.getAbsolute("http://example.com/1")); + DownloadMonitorResult result = dm.downloadAndWait(d); + d = result.get(); + DownloadableLogRecord logRecord = d.getLogRecord(); + assertNotNull(logRecord); + LogPost logPost = logRecord.getLogPost(); + assertNotNull(logPost); + List events = logPost.getEvents(); + assertTrue(events.size() >= 2); + assertTrue(events.get(0) instanceof EnqueueEvent); + assertTrue(events.get(0).getTimestamp() > 0); + assertTrue(events.get(events.size() - 1) instanceof DownloadEvent); + assertTrue(events.get(events.size() - 1).getTimestamp() > 0); + SimplTypesScope.serializeOut(logRecord, "", StringFormat.XML); + } + +} diff --git a/simplTests/test/ecologylab/fundamental/ConstructClassDescriptor.java b/simplTests/test/ecologylab/fundamental/ConstructClassDescriptor.java index 81db9678..403b254f 100644 --- a/simplTests/test/ecologylab/fundamental/ConstructClassDescriptor.java +++ b/simplTests/test/ecologylab/fundamental/ConstructClassDescriptor.java @@ -1,221 +1,221 @@ -package ecologylab.fundamental; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import ecologylab.fundamental.simplescalar.SimpleBoolean; -import ecologylab.fundamental.simplescalar.SimpleByte; -import ecologylab.fundamental.simplescalar.SimpleChar; -import ecologylab.fundamental.simplescalar.SimpleDate; -import ecologylab.fundamental.simplescalar.SimpleDouble; -import ecologylab.fundamental.simplescalar.SimpleFloat; -import ecologylab.fundamental.simplescalar.SimpleInteger; -import ecologylab.fundamental.simplescalar.SimpleJavaURL; -import ecologylab.fundamental.simplescalar.SimpleLong; -import ecologylab.fundamental.simplescalar.SimpleParsedURL; -import ecologylab.fundamental.simplescalar.SimplePattern; -import ecologylab.fundamental.simplescalar.SimpleShort; -import ecologylab.fundamental.simplescalar.SimpleString; -import ecologylab.fundamental.simplescalar.SimpleStringBuilder; -import ecologylab.fundamental.simplescalar.SimpleUUID; -import ecologylab.fundamental.simplescalar.Simpleprimboolean; -import ecologylab.fundamental.simplescalar.Simpleprimbyte; -import ecologylab.fundamental.simplescalar.Simpleprimchar; -import ecologylab.fundamental.simplescalar.Simpleprimdouble; -import ecologylab.fundamental.simplescalar.Simpleprimfloat; -import ecologylab.fundamental.simplescalar.Simpleprimint; -import ecologylab.fundamental.simplescalar.Simpleprimlong; -import ecologylab.fundamental.simplescalar.Simpleprimshort; -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.StringFormat; -import ecologylab.serialization.FieldType; -import ecologylab.serialization.types.scalar.*; - -public class ConstructClassDescriptor { - - - // Todo: Stealthily swap this with a factory method. - private ClassDescriptor ConstructClassDescriptor(Class lass) - { - return ClassDescriptor.getClassDescriptor(lass); - } - - private void testSimpleScalar(Class lass, Class expectedType) - { - ClassDescriptor cd = ConstructClassDescriptor(lass); - - // Get the one field that is in the simple scalar class - assertEquals(1, cd.allFieldDescriptors().size()); - FieldDescriptor fd = cd.allFieldDescriptors().get(0); - assertEquals(lass.getSimpleName().toLowerCase(), fd.getName()); - assertEquals(FieldType.SCALAR, fd.getType()); - // TODO: BUG. //assertEquals(1, fd.getMetaInformation().size()); - assertEquals(expectedType, fd.getScalarType().getClass()); - - // TODO: Roundtrip the class descriptor. - - } - - // TODO: Roundtrip some range of values - - @Test - public void forSimpleBoolean() { - testSimpleScalar(SimpleBoolean.class, ReferenceBooleanType.class); - } - - @Test - public void forSimpleByte() { - testSimpleScalar(SimpleByte.class, ReferenceByteType.class); - } - - @Test - public void forSimpleChar(){ - testSimpleScalar(SimpleChar.class, ReferenceCharType.class); - } - - @Test - public void forSimpleDate(){ - testSimpleScalar(SimpleDate.class, DateType.class); - } - - @Test - public void forSimpleDouble(){ - testSimpleScalar(SimpleDouble.class, ReferenceDoubleType.class); - } - - @Test - public void forSimpleFloat(){ - testSimpleScalar(SimpleFloat.class, ReferenceFloatType.class); - } - - @Test - public void forSimpleInteger() throws SIMPLTranslationException - { - testSimpleScalar(SimpleInteger.class, ReferenceIntegerType.class); - - for(int i=-5; i<5;i++) - { - testSimpleInt(i, StringFormat.XML); - } - - for(int i=-5; i<5;i++) - { - testSimpleInt(i, StringFormat.JSON); - } - - } - - private void testSimpleInt(int i , StringFormat format) throws SIMPLTranslationException - { - SimpleInteger si = new SimpleInteger(); - si.setSimpleInteger(0); - - SimplTypesScope sts = SimplTypesScope.get("inttest", SimpleInteger.class); - - StringBuilder sb = sts.serialize(si, format); - SimpleInteger result = (SimpleInteger)sts.deserialize(sb.toString(), format); - - assertEquals("Roundtrip value did not succeed for default value for: " + format.toString(), si.getSimpleInteger(), result.getSimpleInteger()); - } - - - @Test - public void forSimpleJavaURL(){ - testSimpleScalar(SimpleJavaURL.class, URLType.class); - } - - @Test - public void forSimpleLong(){ - testSimpleScalar(SimpleLong.class, ReferenceLongType.class); - } - - @Test - public void forSimpleParsedURL() - { - testSimpleScalar(SimpleParsedURL.class, ParsedURLType.class); - } - - @Test - public void forSimplePattern() - { - testSimpleScalar(SimplePattern.class, PatternType.class); - } - - @Test - public void forSimplePrimBoolean() - { - testSimpleScalar(Simpleprimboolean.class, BooleanType.class); - } - - @Test - public void forSimplePrimByte() - { - testSimpleScalar(Simpleprimbyte.class, ByteType.class); - } - - @Test - public void forSimplePrimChar() - { - testSimpleScalar(Simpleprimchar.class, CharType.class); - } - - @Test - public void forSimplePrimDouble() - { - testSimpleScalar(Simpleprimdouble.class, DoubleType.class); - } - - @Test - public void forSimplePrimFloat() - { - testSimpleScalar(Simpleprimfloat.class, FloatType.class); - } - - @Test - public void forSimplePrimInt() - { - testSimpleScalar(Simpleprimint.class, IntType.class); - } - - @Test - public void forSimplePrimLong() - { - testSimpleScalar(Simpleprimlong.class, LongType.class); - } - - @Test - public void forSimplePrimShort() - { - testSimpleScalar(Simpleprimshort.class, ShortType.class); - } - - // TODO. - @Test - public void forSimpleShort() - { - testSimpleScalar(SimpleShort.class, ReferenceShortType.class); - } - - @Test - public void forSimpleString() - { - testSimpleScalar(SimpleString.class, StringType.class); - } - - @Test - public void forSimpleStringBuilder() - { - testSimpleScalar(SimpleStringBuilder.class, StringBuilderType.class); - } - - @Test - public void forSimpleUUID() - { - testSimpleScalar(SimpleUUID.class, UUIDType.class); - } - -} +package ecologylab.fundamental; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import ecologylab.fundamental.simplescalar.SimpleBoolean; +import ecologylab.fundamental.simplescalar.SimpleByte; +import ecologylab.fundamental.simplescalar.SimpleChar; +import ecologylab.fundamental.simplescalar.SimpleDate; +import ecologylab.fundamental.simplescalar.SimpleDouble; +import ecologylab.fundamental.simplescalar.SimpleFloat; +import ecologylab.fundamental.simplescalar.SimpleInteger; +import ecologylab.fundamental.simplescalar.SimpleJavaURL; +import ecologylab.fundamental.simplescalar.SimpleLong; +import ecologylab.fundamental.simplescalar.SimpleParsedURL; +import ecologylab.fundamental.simplescalar.SimplePattern; +import ecologylab.fundamental.simplescalar.SimpleShort; +import ecologylab.fundamental.simplescalar.SimpleString; +import ecologylab.fundamental.simplescalar.SimpleStringBuilder; +import ecologylab.fundamental.simplescalar.SimpleUUID; +import ecologylab.fundamental.simplescalar.Simpleprimboolean; +import ecologylab.fundamental.simplescalar.Simpleprimbyte; +import ecologylab.fundamental.simplescalar.Simpleprimchar; +import ecologylab.fundamental.simplescalar.Simpleprimdouble; +import ecologylab.fundamental.simplescalar.Simpleprimfloat; +import ecologylab.fundamental.simplescalar.Simpleprimint; +import ecologylab.fundamental.simplescalar.Simpleprimlong; +import ecologylab.fundamental.simplescalar.Simpleprimshort; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.StringFormat; +import ecologylab.serialization.FieldType; +import ecologylab.serialization.types.scalar.*; + +public class ConstructClassDescriptor { + + + // Todo: Stealthily swap this with a factory method. + private ClassDescriptor ConstructClassDescriptor(Class lass) + { + return ClassDescriptor.getClassDescriptor(lass); + } + + private void testSimpleScalar(Class lass, Class expectedType) + { + ClassDescriptor cd = ConstructClassDescriptor(lass); + + // Get the one field that is in the simple scalar class + assertEquals(1, cd.allFieldDescriptors().size()); + FieldDescriptor fd = cd.allFieldDescriptors().get(0); + assertEquals(lass.getSimpleName().toLowerCase(), fd.getName()); + assertEquals(FieldType.SCALAR, fd.getType()); + // TODO: BUG. //assertEquals(1, fd.getMetaInformation().size()); + assertEquals(expectedType, fd.getScalarType().getClass()); + + // TODO: Roundtrip the class descriptor. + + } + + // TODO: Roundtrip some range of values + + @Test + public void forSimpleBoolean() { + testSimpleScalar(SimpleBoolean.class, ReferenceBooleanType.class); + } + + @Test + public void forSimpleByte() { + testSimpleScalar(SimpleByte.class, ReferenceByteType.class); + } + + @Test + public void forSimpleChar(){ + testSimpleScalar(SimpleChar.class, ReferenceCharType.class); + } + + @Test + public void forSimpleDate(){ + testSimpleScalar(SimpleDate.class, DateType.class); + } + + @Test + public void forSimpleDouble(){ + testSimpleScalar(SimpleDouble.class, ReferenceDoubleType.class); + } + + @Test + public void forSimpleFloat(){ + testSimpleScalar(SimpleFloat.class, ReferenceFloatType.class); + } + + @Test + public void forSimpleInteger() throws SIMPLTranslationException + { + testSimpleScalar(SimpleInteger.class, ReferenceIntegerType.class); + + for(int i=-5; i<5;i++) + { + testSimpleInt(i, StringFormat.XML); + } + + for(int i=-5; i<5;i++) + { + testSimpleInt(i, StringFormat.JSON); + } + + } + + private void testSimpleInt(int i , StringFormat format) throws SIMPLTranslationException + { + SimpleInteger si = new SimpleInteger(); + si.setSimpleInteger(0); + + SimplTypesScope sts = SimplTypesScope.get("inttest", SimpleInteger.class); + + StringBuilder sb = sts.serialize(si, format); + SimpleInteger result = (SimpleInteger)sts.deserialize(sb.toString(), format); + + assertEquals("Roundtrip value did not succeed for default value for: " + format.toString(), si.getSimpleInteger(), result.getSimpleInteger()); + } + + + @Test + public void forSimpleJavaURL(){ + testSimpleScalar(SimpleJavaURL.class, URLType.class); + } + + @Test + public void forSimpleLong(){ + testSimpleScalar(SimpleLong.class, ReferenceLongType.class); + } + + @Test + public void forSimpleParsedURL() + { + testSimpleScalar(SimpleParsedURL.class, ParsedURLType.class); + } + + @Test + public void forSimplePattern() + { + testSimpleScalar(SimplePattern.class, PatternType.class); + } + + @Test + public void forSimplePrimBoolean() + { + testSimpleScalar(Simpleprimboolean.class, BooleanType.class); + } + + @Test + public void forSimplePrimByte() + { + testSimpleScalar(Simpleprimbyte.class, ByteType.class); + } + + @Test + public void forSimplePrimChar() + { + testSimpleScalar(Simpleprimchar.class, CharType.class); + } + + @Test + public void forSimplePrimDouble() + { + testSimpleScalar(Simpleprimdouble.class, DoubleType.class); + } + + @Test + public void forSimplePrimFloat() + { + testSimpleScalar(Simpleprimfloat.class, FloatType.class); + } + + @Test + public void forSimplePrimInt() + { + testSimpleScalar(Simpleprimint.class, IntType.class); + } + + @Test + public void forSimplePrimLong() + { + testSimpleScalar(Simpleprimlong.class, LongType.class); + } + + @Test + public void forSimplePrimShort() + { + testSimpleScalar(Simpleprimshort.class, ShortType.class); + } + + // TODO. + @Test + public void forSimpleShort() + { + testSimpleScalar(SimpleShort.class, ReferenceShortType.class); + } + + @Test + public void forSimpleString() + { + testSimpleScalar(SimpleString.class, StringType.class); + } + + @Test + public void forSimpleStringBuilder() + { + testSimpleScalar(SimpleStringBuilder.class, StringBuilderType.class); + } + + @Test + public void forSimpleUUID() + { + testSimpleScalar(SimpleUUID.class, UUIDType.class); + } + +} diff --git a/simplTests/test/ecologylab/fundamental/CreateSimpleScalars.java b/simplTests/test/ecologylab/fundamental/CreateSimpleScalars.java index 3dc8f6fb..690613dc 100644 --- a/simplTests/test/ecologylab/fundamental/CreateSimpleScalars.java +++ b/simplTests/test/ecologylab/fundamental/CreateSimpleScalars.java @@ -1,100 +1,100 @@ -package ecologylab.fundamental; - -import java.io.File; -import java.io.IOException; -import com.google.common.io.Files; -import com.google.common.base.Charsets; - -public class CreateSimpleScalars { - - - static String getRepr(String name, String type, String include) - { - StringBuilder sb = new StringBuilder(); - - sb.append("package ecologylab.fundamental.simplescalar;\r\n"); - - if(!include.isEmpty()){ - sb.append("import "); - sb.append(include); - sb.append(";\r\n"); - } - - sb.append("import ecologylab.serialization.annotations.simpl_scalar;\r\n"); - sb.append(String.format("public class Simple%s {\r\n", name)); - sb.append("\t@simpl_scalar\r\n"); - sb.append(String.format("\tprivate %s simple%s;\r\n", type, name.toLowerCase())); - sb.append(String.format("\r\n\tpublic %s getSimple%s(){ \r\n", type, name)); - sb.append(String.format("\t\t return this.simple%s;\r\n", name.toLowerCase())); - sb.append("\t}\r\n"); - sb.append(String.format("\r\n\tpublic void setSimple%s(%s value){\r\n", name, type)); - sb.append(String.format("\t\tthis.simple%s = value;\r\n", name.toLowerCase())); - sb.append("\t}\r\n"); - sb.append("}\r\n"); - - return sb.toString(); - } - - - static File getFor(String name) throws IOException - { - File f = new File("C:\\Users\\tomwhite\\Documents\\test\\Simple" + name + ".java"); - f.createNewFile(); - return f; - } - - static void Create(String name, String type, String include) throws IOException - { - File f = getFor(name); - - Files.write(getRepr(name, type, include), f, Charsets.UTF_8); - } - - /** - * @param args - * @throws IOException - */ - public static void main(String[] args) throws IOException { - // TODO Auto-generated method stub - - Create("Integer", "Integer", ""); - Create("primint", "int" , ""); - - Create("String", "String", ""); - - Create("primdouble", "double", ""); - Create("Double", "Double", ""); - - Create("primfloat", "float", ""); - Create("Float", "Float",""); - - Create("primshort", "short", ""); - Create("Short", "Short",""); - - Create("primlong", "long", ""); - Create("Long", "Long", ""); - - Create("Boolean", "Boolean", ""); - Create("primboolean", "boolean", ""); - - Create("Byte", "Byte", ""); - Create("primbyte","byte",""); - - Create("Char", "Character", ""); - Create("primchar", "char", ""); - - Create("Date", "Date", "java.util.Date"); - - Create("ParsedURL", "ParsedURL", "ecologylab.net.ParsedURL"); - - Create("Pattern", "Pattern", "java.util.regex.Pattern"); - - Create("StringBuilder", "StringBuilder", ""); - - Create("JavaURL", "URL", "java.net.URL"); - - Create("UUID", "UUID", "java.util.UUID"); - - } - -} +package ecologylab.fundamental; + +import java.io.File; +import java.io.IOException; +import com.google.common.io.Files; +import com.google.common.base.Charsets; + +public class CreateSimpleScalars { + + + static String getRepr(String name, String type, String include) + { + StringBuilder sb = new StringBuilder(); + + sb.append("package ecologylab.fundamental.simplescalar;\r\n"); + + if(!include.isEmpty()){ + sb.append("import "); + sb.append(include); + sb.append(";\r\n"); + } + + sb.append("import ecologylab.serialization.annotations.simpl_scalar;\r\n"); + sb.append(String.format("public class Simple%s {\r\n", name)); + sb.append("\t@simpl_scalar\r\n"); + sb.append(String.format("\tprivate %s simple%s;\r\n", type, name.toLowerCase())); + sb.append(String.format("\r\n\tpublic %s getSimple%s(){ \r\n", type, name)); + sb.append(String.format("\t\t return this.simple%s;\r\n", name.toLowerCase())); + sb.append("\t}\r\n"); + sb.append(String.format("\r\n\tpublic void setSimple%s(%s value){\r\n", name, type)); + sb.append(String.format("\t\tthis.simple%s = value;\r\n", name.toLowerCase())); + sb.append("\t}\r\n"); + sb.append("}\r\n"); + + return sb.toString(); + } + + + static File getFor(String name) throws IOException + { + File f = new File("C:\\Users\\tomwhite\\Documents\\test\\Simple" + name + ".java"); + f.createNewFile(); + return f; + } + + static void Create(String name, String type, String include) throws IOException + { + File f = getFor(name); + + Files.write(getRepr(name, type, include), f, Charsets.UTF_8); + } + + /** + * @param args + * @throws IOException + */ + public static void main(String[] args) throws IOException { + // TODO Auto-generated method stub + + Create("Integer", "Integer", ""); + Create("primint", "int" , ""); + + Create("String", "String", ""); + + Create("primdouble", "double", ""); + Create("Double", "Double", ""); + + Create("primfloat", "float", ""); + Create("Float", "Float",""); + + Create("primshort", "short", ""); + Create("Short", "Short",""); + + Create("primlong", "long", ""); + Create("Long", "Long", ""); + + Create("Boolean", "Boolean", ""); + Create("primboolean", "boolean", ""); + + Create("Byte", "Byte", ""); + Create("primbyte","byte",""); + + Create("Char", "Character", ""); + Create("primchar", "char", ""); + + Create("Date", "Date", "java.util.Date"); + + Create("ParsedURL", "ParsedURL", "ecologylab.net.ParsedURL"); + + Create("Pattern", "Pattern", "java.util.regex.Pattern"); + + Create("StringBuilder", "StringBuilder", ""); + + Create("JavaURL", "URL", "java.net.URL"); + + Create("UUID", "UUID", "java.util.UUID"); + + } + +} diff --git a/simplTests/test/ecologylab/fundamental/DBALTests.java b/simplTests/test/ecologylab/fundamental/DBALTests.java index c661b57e..4084054d 100644 --- a/simplTests/test/ecologylab/fundamental/DBALTests.java +++ b/simplTests/test/ecologylab/fundamental/DBALTests.java @@ -1,86 +1,86 @@ -package ecologylab.fundamental; - -import java.util.ArrayList; - -import org.junit.Test; -import static org.junit.Assert.*; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.XMLTools; -import ecologylab.serialization.annotations.FieldUsage; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_scalar; - -public class DBALTests { - //TODO: validation on these is super sparse... just to prove out where - // exceptions happen. Will fix eventually. - - @Test - public void simpl_Collection_of_enums_transmitsNameIntoFD() - { - final class myCollectionClass - { - @simpl_collection("collection_test") - private ArrayList collectionTest; - } - - String tagName = XMLTools.getXmlTagName(myCollectionClass.class.getDeclaredFields()[0]); - assertNotNull(tagName); - System.out.println(tagName); - - ClassDescriptor cd = ClassDescriptor.getClassDescriptor(myCollectionClass.class); - FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); - assertNotNull(fd.getTagName()); - } - - @Test - public void simpl_collection_of_composites_transmistNameIntoFD() - { - final class someCompositeClass - { - @simpl_scalar - private Integer myInteger; - } - - final class myCollectionClass - { - @simpl_collection("excluded_usage") - private ArrayList excludedUsages; - } - - ClassDescriptor cd = ClassDescriptor.getClassDescriptor(myCollectionClass.class); - FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); - assertNotNull(fd.getTagName()); - } - - @Test - public void simpl_Collection_of_scalars_transmitsNameIntoFD() - { - final class myCollectionClass - { - @simpl_collection("excluded_usage") - private ArrayList excludedUsages; - } - - ClassDescriptor cd = ClassDescriptor.getClassDescriptor(myCollectionClass.class); - FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); - assertNotNull(fd.getTagName()); - } - - @Test - public void simpl_collection_of_collection_of_scalars_works() - { - final class myCollectionClass - { - @simpl_collection("excluded_usage") - private ArrayList> excludedUsages; - } - - ClassDescriptor cd = ClassDescriptor.getClassDescriptor(myCollectionClass.class); - FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); - assertNotNull(fd.getTagName()); - } - - -} +package ecologylab.fundamental; + +import java.util.ArrayList; + +import org.junit.Test; +import static org.junit.Assert.*; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.FieldUsage; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_scalar; + +public class DBALTests { + //TODO: validation on these is super sparse... just to prove out where + // exceptions happen. Will fix eventually. + + @Test + public void simpl_Collection_of_enums_transmitsNameIntoFD() + { + final class myCollectionClass + { + @simpl_collection("collection_test") + private ArrayList collectionTest; + } + + String tagName = XMLTools.getXmlTagName(myCollectionClass.class.getDeclaredFields()[0]); + assertNotNull(tagName); + System.out.println(tagName); + + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(myCollectionClass.class); + FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); + assertNotNull(fd.getTagName()); + } + + @Test + public void simpl_collection_of_composites_transmistNameIntoFD() + { + final class someCompositeClass + { + @simpl_scalar + private Integer myInteger; + } + + final class myCollectionClass + { + @simpl_collection("excluded_usage") + private ArrayList excludedUsages; + } + + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(myCollectionClass.class); + FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); + assertNotNull(fd.getTagName()); + } + + @Test + public void simpl_Collection_of_scalars_transmitsNameIntoFD() + { + final class myCollectionClass + { + @simpl_collection("excluded_usage") + private ArrayList excludedUsages; + } + + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(myCollectionClass.class); + FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); + assertNotNull(fd.getTagName()); + } + + @Test + public void simpl_collection_of_collection_of_scalars_works() + { + final class myCollectionClass + { + @simpl_collection("excluded_usage") + private ArrayList> excludedUsages; + } + + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(myCollectionClass.class); + FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); + assertNotNull(fd.getTagName()); + } + + +} diff --git a/simplTests/test/ecologylab/fundamental/DeSerializingDescriptors.java b/simplTests/test/ecologylab/fundamental/DeSerializingDescriptors.java index cbf59cbd..03182fbf 100644 --- a/simplTests/test/ecologylab/fundamental/DeSerializingDescriptors.java +++ b/simplTests/test/ecologylab/fundamental/DeSerializingDescriptors.java @@ -1,67 +1,67 @@ -package ecologylab.fundamental; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.JSONTools; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -public class DeSerializingDescriptors extends Assert -{ - - @Before - public void init() - { - SimplTypesScope.graphSwitch = GRAPH_SWITCH.ON; - } - - public void deSerializeDescriptorsJSON() throws SIMPLTranslationException, IOException - { - SimplTypesScope tscope = SimplTypesScope.get("test-de/serialize descriptors in json", - FieldDescriptor.class, - ClassDescriptor.class, - SimplTypesScope.class); - String json = SimplTypesScope.serialize(tscope, StringFormat.JSON).toString(); - System.out.println("serialized json string:\n" + json); - assertTrue(JSONTools.validate(json)); - -// File testScopeFile = new File("data/test-deserialize-descriptors-scope.json"); -// assertTrue(testScopeFile.exists()); -// json = loadJSONStringFromFile(testScopeFile); - - SimplTypesScope newTscope = (SimplTypesScope) tscope.deserialize(json, StringFormat.JSON); -// SimplTypesScope newTscope = (SimplTypesScope) tscope.deserialize(testScopeFile, Format.JSON); - assertNotNull(newTscope); - assertNotNull(newTscope.getClassDescriptorBySimpleName("FieldDescriptor")); - assertNotNull(newTscope.getClassDescriptorBySimpleName("ClassDescriptor")); - assertNotNull(newTscope.getClassDescriptorBySimpleName("SimplTypesScope")); - } - - - static String loadJSONStringFromFile(File file) throws IOException - { - StringBuilder sb = new StringBuilder(); - BufferedReader br = new BufferedReader(new FileReader(file)); - while (true) - { - String line = br.readLine(); - if (line == null) - break; - sb.append(line.trim()); - } - return sb.toString(); - } - -} +package ecologylab.fundamental; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.JSONTools; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.SimplTypesScope.GRAPH_SWITCH; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +public class DeSerializingDescriptors extends Assert +{ + + @Before + public void init() + { + SimplTypesScope.graphSwitch = GRAPH_SWITCH.ON; + } + + public void deSerializeDescriptorsJSON() throws SIMPLTranslationException, IOException + { + SimplTypesScope tscope = SimplTypesScope.get("test-de/serialize descriptors in json", + FieldDescriptor.class, + ClassDescriptor.class, + SimplTypesScope.class); + String json = SimplTypesScope.serialize(tscope, StringFormat.JSON).toString(); + System.out.println("serialized json string:\n" + json); + assertTrue(JSONTools.validate(json)); + +// File testScopeFile = new File("data/test-deserialize-descriptors-scope.json"); +// assertTrue(testScopeFile.exists()); +// json = loadJSONStringFromFile(testScopeFile); + + SimplTypesScope newTscope = (SimplTypesScope) tscope.deserialize(json, StringFormat.JSON); +// SimplTypesScope newTscope = (SimplTypesScope) tscope.deserialize(testScopeFile, Format.JSON); + assertNotNull(newTscope); + assertNotNull(newTscope.getClassDescriptorBySimpleName("FieldDescriptor")); + assertNotNull(newTscope.getClassDescriptorBySimpleName("ClassDescriptor")); + assertNotNull(newTscope.getClassDescriptorBySimpleName("SimplTypesScope")); + } + + + static String loadJSONStringFromFile(File file) throws IOException + { + StringBuilder sb = new StringBuilder(); + BufferedReader br = new BufferedReader(new FileReader(file)); + while (true) + { + String line = br.readLine(); + if (line == null) + break; + sb.append(line.trim()); + } + return sb.toString(); + } + +} diff --git a/simplTests/test/ecologylab/fundamental/DescriptorsCanBeDescribed.java b/simplTests/test/ecologylab/fundamental/DescriptorsCanBeDescribed.java index b7f243ed..24606543 100644 --- a/simplTests/test/ecologylab/fundamental/DescriptorsCanBeDescribed.java +++ b/simplTests/test/ecologylab/fundamental/DescriptorsCanBeDescribed.java @@ -1,46 +1,46 @@ -package ecologylab.fundamental; - -import org.junit.Before; -import org.junit.Test; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.SimplTypesScope; - -public class DescriptorsCanBeDescribed{ - - - @Before - public void ResetSTS() - { - SimplTypesScope.ResetAllTypesScopes(); - } - - @Test - public void FieldDescriptorCanBeDescribed() - { - ClassDescriptor cd = ClassDescriptor.getClassDescriptor(FieldDescriptor.class); - } - - @Test - public void ClassDescriptorCanBeDescribed() - { - ClassDescriptor cd = ClassDescriptor.getClassDescriptor(ClassDescriptor.class); - } - - - @Test - public void YinsCase() - { - SimplTypesScope tscope = SimplTypesScope.get("test-de/serialize descriptors in json", - FieldDescriptor.class, - ClassDescriptor.class, - SimplTypesScope.class); - - } - //TODO: Better validation on these. - //They're sparse because they're just trying to catch silly exceptions. - - - +package ecologylab.fundamental; + +import org.junit.Before; +import org.junit.Test; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.SimplTypesScope; + +public class DescriptorsCanBeDescribed{ + + + @Before + public void ResetSTS() + { + SimplTypesScope.ResetAllTypesScopes(); + } + + @Test + public void FieldDescriptorCanBeDescribed() + { + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(FieldDescriptor.class); + } + + @Test + public void ClassDescriptorCanBeDescribed() + { + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(ClassDescriptor.class); + } + + + @Test + public void YinsCase() + { + SimplTypesScope tscope = SimplTypesScope.get("test-de/serialize descriptors in json", + FieldDescriptor.class, + ClassDescriptor.class, + SimplTypesScope.class); + + } + //TODO: Better validation on these. + //They're sparse because they're just trying to catch silly exceptions. + + + } \ No newline at end of file diff --git a/simplTests/test/ecologylab/fundamental/EnumDescriptionDeSerializationTest.java b/simplTests/test/ecologylab/fundamental/EnumDescriptionDeSerializationTest.java index eb190118..ebc5f369 100644 --- a/simplTests/test/ecologylab/fundamental/EnumDescriptionDeSerializationTest.java +++ b/simplTests/test/ecologylab/fundamental/EnumDescriptionDeSerializationTest.java @@ -1,112 +1,112 @@ -package ecologylab.fundamental; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.EnumerationDescriptor; -import ecologylab.serialization.SIMPLDescriptionException; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.primaryScenarioEnum; -import ecologylab.serialization.secondaryScenarioEnum; -import ecologylab.serialization.formatenums.StringFormat; - -public class EnumDescriptionDeSerializationTest { - - - @Test - public void letsTrySomethingTricksy() - { - ClassDescriptor cd = ClassDescriptor.getClassDescriptor(primaryScenarioEnum.class); - cd.toString(); - } - - @Test - public void EnumDescriptorCanBeDescribed() - { - ClassDescriptor cd = ClassDescriptor.getClassDescriptor(EnumerationDescriptor.class); - } - - @Test - public void descriptionWillCorrectlySerializeToXML() throws SIMPLDescriptionException, SIMPLTranslationException - { - EnumerationDescriptionTestPerFormat(primaryScenarioEnum.class, StringFormat.XML, false); - } - - @Test - public void descriptionWillCorrectlySerializeToJSON() throws SIMPLDescriptionException, SIMPLTranslationException - { - EnumerationDescriptionTestPerFormat(primaryScenarioEnum.class, StringFormat.JSON, false); - } - - @Test - public void descriptionWithValuesWillCorrectlySerializeToXML() throws SIMPLDescriptionException, SIMPLTranslationException - { - EnumerationDescriptionTestPerFormat(secondaryScenarioEnum.class, StringFormat.XML, true); - } - - @Test - public void descriptionWithValuesWillCorrectlySerializeToJSON() throws SIMPLDescriptionException, SIMPLTranslationException - { - EnumerationDescriptionTestPerFormat(secondaryScenarioEnum.class, StringFormat.JSON, true); - } - - private void EnumerationDescriptionTestPerFormat(Class forEnumClass, StringFormat theFormat, boolean validateValues) throws SIMPLDescriptionException, SIMPLTranslationException - { - EnumerationDescriptor primaryScenario = EnumerationDescriptor.get(forEnumClass); - - SimplTypesScope sts = SimplTypesScope.get("enumDescTest" + theFormat.toString(), EnumerationDescriptor.class); - - Class tag = sts.getClassByTag("enumeration_descriptor"); - assertNotNull("Class not in STS!", tag); - StringBuilder staticSerialized = SimplTypesScope.serialize(primaryScenario, theFormat); - StringBuilder specificSTSSerialized = sts.serialize(primaryScenario, theFormat); - - assertTrue(staticSerialized.toString().equals(specificSTSSerialized.toString())); - System.out.println(staticSerialized.toString()); - System.out.println(specificSTSSerialized.toString()); - - EnumerationDescriptor recaptured = (EnumerationDescriptor) sts.deserialize(staticSerialized.toString(), theFormat); - performBasicValidations(forEnumClass, recaptured); - - if(validateValues) - { - performValueValidation(recaptured); - } - } - - /** - * This handles some of the validations that should apply for most of the test cases; - * these have been copy pasted from the prior test case so they can be reused... - * I could have refactored this in the first test case to a method call, but I felt it was nicer w/ the core assumptions there. - * @param ed - */ - private void performBasicValidations(Class enumClass, EnumerationDescriptor ed) - { - - assertEquals("The packageName must be correct" , enumClass.getPackage().getName(), ed.getPackageName()); - assertEquals("The javaName must be correct", enumClass.getName(), ed.getJavaTypeName()); - assertEquals("The Simpl name must be correct", enumClass.getSimpleName(), ed.getName()); - - assertEquals("There should be three entries for this enum", 3, ed.getEnumerationEntries().size()); - - assertTrue("Should contain all of the values of the enum! Missing first", ed.containsEntry("firstValue")); - assertTrue("Should contain all of the values of the enum! Missing second", ed.containsEntry("secondValue")); - assertTrue("Should contain all of the values of the enum! Missing third", ed.containsEntry("thirdValue")); - assertFalse("Should not contain a value that isn't in the enum! There are no Jibbles here!", ed.containsEntry("jibbles")); - assertFalse("Should be case sensitive! FIRSTENTRY ignores casing.", ed.containsEntry("FIRSTENTRY")); - } - - private void performValueValidation(EnumerationDescriptor ed) - { - assertEquals(new Integer(3), ed.getEntryEnumIntegerValue("firstValue")); - assertEquals(new Integer(5), ed.getEntryEnumIntegerValue("secondValue")); - assertEquals(new Integer(7), ed.getEntryEnumIntegerValue("thirdValue")); - - assertEquals("firstValue", ed.getEntryEnumFromValue(3).toString()); - assertEquals("secondValue", ed.getEntryEnumFromValue(5).toString()); - assertEquals("thirdValue", ed.getEntryEnumFromValue(7).toString()); - } -} +package ecologylab.fundamental; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.EnumerationDescriptor; +import ecologylab.serialization.SIMPLDescriptionException; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.primaryScenarioEnum; +import ecologylab.serialization.secondaryScenarioEnum; +import ecologylab.serialization.formatenums.StringFormat; + +public class EnumDescriptionDeSerializationTest { + + + @Test + public void letsTrySomethingTricksy() + { + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(primaryScenarioEnum.class); + cd.toString(); + } + + @Test + public void EnumDescriptorCanBeDescribed() + { + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(EnumerationDescriptor.class); + } + + @Test + public void descriptionWillCorrectlySerializeToXML() throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptionTestPerFormat(primaryScenarioEnum.class, StringFormat.XML, false); + } + + @Test + public void descriptionWillCorrectlySerializeToJSON() throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptionTestPerFormat(primaryScenarioEnum.class, StringFormat.JSON, false); + } + + @Test + public void descriptionWithValuesWillCorrectlySerializeToXML() throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptionTestPerFormat(secondaryScenarioEnum.class, StringFormat.XML, true); + } + + @Test + public void descriptionWithValuesWillCorrectlySerializeToJSON() throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptionTestPerFormat(secondaryScenarioEnum.class, StringFormat.JSON, true); + } + + private void EnumerationDescriptionTestPerFormat(Class forEnumClass, StringFormat theFormat, boolean validateValues) throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptor primaryScenario = EnumerationDescriptor.get(forEnumClass); + + SimplTypesScope sts = SimplTypesScope.get("enumDescTest" + theFormat.toString(), EnumerationDescriptor.class); + + Class tag = sts.getClassByTag("enumeration_descriptor"); + assertNotNull("Class not in STS!", tag); + StringBuilder staticSerialized = SimplTypesScope.serialize(primaryScenario, theFormat); + StringBuilder specificSTSSerialized = sts.serialize(primaryScenario, theFormat); + + assertTrue(staticSerialized.toString().equals(specificSTSSerialized.toString())); + System.out.println(staticSerialized.toString()); + System.out.println(specificSTSSerialized.toString()); + + EnumerationDescriptor recaptured = (EnumerationDescriptor) sts.deserialize(staticSerialized.toString(), theFormat); + performBasicValidations(forEnumClass, recaptured); + + if(validateValues) + { + performValueValidation(recaptured); + } + } + + /** + * This handles some of the validations that should apply for most of the test cases; + * these have been copy pasted from the prior test case so they can be reused... + * I could have refactored this in the first test case to a method call, but I felt it was nicer w/ the core assumptions there. + * @param ed + */ + private void performBasicValidations(Class enumClass, EnumerationDescriptor ed) + { + + assertEquals("The packageName must be correct" , enumClass.getPackage().getName(), ed.getPackageName()); + assertEquals("The javaName must be correct", enumClass.getName(), ed.getJavaTypeName()); + assertEquals("The Simpl name must be correct", enumClass.getSimpleName(), ed.getName()); + + assertEquals("There should be three entries for this enum", 3, ed.getEnumerationEntries().size()); + + assertTrue("Should contain all of the values of the enum! Missing first", ed.containsEntry("firstValue")); + assertTrue("Should contain all of the values of the enum! Missing second", ed.containsEntry("secondValue")); + assertTrue("Should contain all of the values of the enum! Missing third", ed.containsEntry("thirdValue")); + assertFalse("Should not contain a value that isn't in the enum! There are no Jibbles here!", ed.containsEntry("jibbles")); + assertFalse("Should be case sensitive! FIRSTENTRY ignores casing.", ed.containsEntry("FIRSTENTRY")); + } + + private void performValueValidation(EnumerationDescriptor ed) + { + assertEquals(new Integer(3), ed.getEntryEnumIntegerValue("firstValue")); + assertEquals(new Integer(5), ed.getEntryEnumIntegerValue("secondValue")); + assertEquals(new Integer(7), ed.getEntryEnumIntegerValue("thirdValue")); + + assertEquals("firstValue", ed.getEntryEnumFromValue(3).toString()); + assertEquals("secondValue", ed.getEntryEnumFromValue(5).toString()); + assertEquals("thirdValue", ed.getEntryEnumFromValue(7).toString()); + } +} diff --git a/simplTests/test/ecologylab/fundamental/EnumerationSerializationDeserialization.java b/simplTests/test/ecologylab/fundamental/EnumerationSerializationDeserialization.java index ac87bd50..a902761f 100644 --- a/simplTests/test/ecologylab/fundamental/EnumerationSerializationDeserialization.java +++ b/simplTests/test/ecologylab/fundamental/EnumerationSerializationDeserialization.java @@ -1,125 +1,125 @@ -package ecologylab.fundamental; - -import static org.junit.Assert.*; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.FieldType; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.primaryScenarioEnum; -import ecologylab.serialization.secondaryScenarioEnum; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.formatenums.StringFormat; - -public class EnumerationSerializationDeserialization { - - // TODO: MAPS... OTHER FORMATS. :3 - - private void validateBasicSerializationCases(Object toSerialize, String toExpect, StringFormat format) throws SIMPLTranslationException - { - StringBuilder result = SimplTypesScope.serialize(toSerialize, format); - - System.out.println(result.toString()); - // Really sneaky way to check if firstValue is in the XML / JSON. - assertTrue(result.toString().contains(toExpect)); - } - - @Test - public void testSerializeBasicScalar() throws SIMPLTranslationException - { - basicEnumerationScalar baseCase = new basicEnumerationScalar(); - baseCase.ourEnum = primaryScenarioEnum.firstValue; - - validateBasicSerializationCases(baseCase, "firstValue", StringFormat.XML); - validateBasicSerializationCases(baseCase, "firstValue", StringFormat.JSON); - - // Should like so in XML: - // - // JSON is: {"basic_enumeration_scalar":{"our_enum":"firstValue"}} - - } - - // These are pretty much the same for serialize - // deserialize is going ot be diferent though. :3 - @Test - public void testSerializeValuedScalar() throws SIMPLTranslationException - { - customValuedEnumerationScalar valuedCase = new customValuedEnumerationScalar(); - valuedCase.ourEnum = secondaryScenarioEnum.secondValue; - - validateBasicSerializationCases(valuedCase, "secondValue", StringFormat.XML); - validateBasicSerializationCases(valuedCase, "secondValue", StringFormat.JSON); - - // - //{"custom_valued_enumeration_scalar":{"our_enum":"secondValue"}} - } - - private static SimplTypesScope ourSTS = SimplTypesScope.get("enumTestsDeSerialize", primaryScenarioEnum.class, secondaryScenarioEnum.class, - customValuedEnumerationScalar.class, basicEnumerationScalar.class, basicEnumerationList.class); - - - private void validateDeserialization(String representation, StringFormat format, Object expected) throws SIMPLTranslationException, IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException - { - Object result = ourSTS.deserialize(representation, format); - - Field ourField = result.getClass().getField("ourEnum"); - ourField.setAccessible(true); - - Object value = ourField.get(result); - assertEquals(expected, value); - } - - @Test - public void testDeserializeBaseCase() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, SIMPLTranslationException - { - basicEnumerationScalar baseCase = new basicEnumerationScalar(); - baseCase.ourEnum = primaryScenarioEnum.firstValue; - - validateDeserialization("", StringFormat.XML, primaryScenarioEnum.firstValue); - validateDeserialization("{\"basic_enumeration_scalar\":{\"our_enum\":\"secondValue\"}}", StringFormat.JSON, primaryScenarioEnum.secondValue); - } - - @Test - public void testDeserializeCustomValuedCase() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, SIMPLTranslationException - { - validateDeserialization("", StringFormat.XML, secondaryScenarioEnum.secondValue); - validateDeserialization("", StringFormat.XML, secondaryScenarioEnum.secondValue); - - validateDeserialization("{\"custom_valued_enumeration_scalar\":{\"our_enum\":\"secondValue\"}}", StringFormat.JSON, secondaryScenarioEnum.secondValue); - validateDeserialization("{\"custom_valued_enumeration_scalar\":{\"our_enum\":\"5\"}}", StringFormat.JSON, secondaryScenarioEnum.secondValue); - } - - - - @Test - public void EnumerationListsCanBeDescribed() - { - ClassDescriptor cd = ClassDescriptor.getClassDescriptor(basicEnumerationList.class); - assertEquals(1,cd.allFieldDescriptors().size()); - - FieldDescriptor fd = (FieldDescriptor) cd.allFieldDescriptors().get(0); - - // Yeah, that's not a guarentee. I don't feel comfy making enums "elements" - // but it makes sense insofar as they rely upon the type scope. :\ - - - assertEquals(FieldType.COLLECTION_ELEMENT, fd.getType()); - assertEquals("ourList", fd.getName()); - } - - - - - // TODO: Tests for lists; let's get the base case fixed first. - - - - -} +package ecologylab.fundamental; + +import static org.junit.Assert.*; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.FieldType; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.primaryScenarioEnum; +import ecologylab.serialization.secondaryScenarioEnum; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.formatenums.StringFormat; + +public class EnumerationSerializationDeserialization { + + // TODO: MAPS... OTHER FORMATS. :3 + + private void validateBasicSerializationCases(Object toSerialize, String toExpect, StringFormat format) throws SIMPLTranslationException + { + StringBuilder result = SimplTypesScope.serialize(toSerialize, format); + + System.out.println(result.toString()); + // Really sneaky way to check if firstValue is in the XML / JSON. + assertTrue(result.toString().contains(toExpect)); + } + + @Test + public void testSerializeBasicScalar() throws SIMPLTranslationException + { + basicEnumerationScalar baseCase = new basicEnumerationScalar(); + baseCase.ourEnum = primaryScenarioEnum.firstValue; + + validateBasicSerializationCases(baseCase, "firstValue", StringFormat.XML); + validateBasicSerializationCases(baseCase, "firstValue", StringFormat.JSON); + + // Should like so in XML: + // + // JSON is: {"basic_enumeration_scalar":{"our_enum":"firstValue"}} + + } + + // These are pretty much the same for serialize + // deserialize is going ot be diferent though. :3 + @Test + public void testSerializeValuedScalar() throws SIMPLTranslationException + { + customValuedEnumerationScalar valuedCase = new customValuedEnumerationScalar(); + valuedCase.ourEnum = secondaryScenarioEnum.secondValue; + + validateBasicSerializationCases(valuedCase, "secondValue", StringFormat.XML); + validateBasicSerializationCases(valuedCase, "secondValue", StringFormat.JSON); + + // + //{"custom_valued_enumeration_scalar":{"our_enum":"secondValue"}} + } + + private static SimplTypesScope ourSTS = SimplTypesScope.get("enumTestsDeSerialize", primaryScenarioEnum.class, secondaryScenarioEnum.class, + customValuedEnumerationScalar.class, basicEnumerationScalar.class, basicEnumerationList.class); + + + private void validateDeserialization(String representation, StringFormat format, Object expected) throws SIMPLTranslationException, IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException + { + Object result = ourSTS.deserialize(representation, format); + + Field ourField = result.getClass().getField("ourEnum"); + ourField.setAccessible(true); + + Object value = ourField.get(result); + assertEquals(expected, value); + } + + @Test + public void testDeserializeBaseCase() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, SIMPLTranslationException + { + basicEnumerationScalar baseCase = new basicEnumerationScalar(); + baseCase.ourEnum = primaryScenarioEnum.firstValue; + + validateDeserialization("", StringFormat.XML, primaryScenarioEnum.firstValue); + validateDeserialization("{\"basic_enumeration_scalar\":{\"our_enum\":\"secondValue\"}}", StringFormat.JSON, primaryScenarioEnum.secondValue); + } + + @Test + public void testDeserializeCustomValuedCase() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, SIMPLTranslationException + { + validateDeserialization("", StringFormat.XML, secondaryScenarioEnum.secondValue); + validateDeserialization("", StringFormat.XML, secondaryScenarioEnum.secondValue); + + validateDeserialization("{\"custom_valued_enumeration_scalar\":{\"our_enum\":\"secondValue\"}}", StringFormat.JSON, secondaryScenarioEnum.secondValue); + validateDeserialization("{\"custom_valued_enumeration_scalar\":{\"our_enum\":\"5\"}}", StringFormat.JSON, secondaryScenarioEnum.secondValue); + } + + + + @Test + public void EnumerationListsCanBeDescribed() + { + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(basicEnumerationList.class); + assertEquals(1,cd.allFieldDescriptors().size()); + + FieldDescriptor fd = (FieldDescriptor) cd.allFieldDescriptors().get(0); + + // Yeah, that's not a guarentee. I don't feel comfy making enums "elements" + // but it makes sense insofar as they rely upon the type scope. :\ + + + assertEquals(FieldType.COLLECTION_ELEMENT, fd.getType()); + assertEquals("ourList", fd.getName()); + } + + + + + // TODO: Tests for lists; let's get the base case fixed first. + + + + +} diff --git a/simplTests/test/ecologylab/fundamental/FieldDescriptionTest.java b/simplTests/test/ecologylab/fundamental/FieldDescriptionTest.java index b76b6c75..4917b765 100644 --- a/simplTests/test/ecologylab/fundamental/FieldDescriptionTest.java +++ b/simplTests/test/ecologylab/fundamental/FieldDescriptionTest.java @@ -1,35 +1,35 @@ -package ecologylab.fundamental; - -import org.junit.Test; -import static org.junit.Assert.*; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.FieldType; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.primaryScenarioEnum; -import ecologylab.serialization.annotations.simpl_scalar; - -public class FieldDescriptionTest { - - @Test - public void testDescribeEnumerationField() throws SIMPLTranslationException{ - final class anEnumField - { - @simpl_scalar - private primaryScenarioEnum myEnum; - } - - ClassDescriptor cd = ClassDescriptor.getClassDescriptor(anEnumField.class); - assertEquals(1,cd.allFieldDescriptors().size()); - - FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); - assertEquals(FieldType.SCALAR, fd.getType()); - assertEquals(primaryScenarioEnum.class, fd.getFieldType()); - assertEquals(true, fd.isEnum()); - assertNotNull(fd.getEnumerationDescriptor()); - assertEquals("firstValue", fd.getEnumerationDescriptor().marshal(primaryScenarioEnum.firstValue)); - assertEquals(primaryScenarioEnum.firstValue, fd.getEnumerationDescriptor().unmarshal("firstValue")); - - } -} +package ecologylab.fundamental; + +import org.junit.Test; +import static org.junit.Assert.*; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.FieldType; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.primaryScenarioEnum; +import ecologylab.serialization.annotations.simpl_scalar; + +public class FieldDescriptionTest { + + @Test + public void testDescribeEnumerationField() throws SIMPLTranslationException{ + final class anEnumField + { + @simpl_scalar + private primaryScenarioEnum myEnum; + } + + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(anEnumField.class); + assertEquals(1,cd.allFieldDescriptors().size()); + + FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); + assertEquals(FieldType.SCALAR, fd.getType()); + assertEquals(primaryScenarioEnum.class, fd.getFieldType()); + assertEquals(true, fd.isEnum()); + assertNotNull(fd.getEnumerationDescriptor()); + assertEquals("firstValue", fd.getEnumerationDescriptor().marshal(primaryScenarioEnum.firstValue)); + assertEquals(primaryScenarioEnum.firstValue, fd.getEnumerationDescriptor().unmarshal("firstValue")); + + } +} diff --git a/simplTests/test/ecologylab/fundamental/ListDeSerializationTests.java b/simplTests/test/ecologylab/fundamental/ListDeSerializationTests.java index 80cb04c8..0fd62c54 100644 --- a/simplTests/test/ecologylab/fundamental/ListDeSerializationTests.java +++ b/simplTests/test/ecologylab/fundamental/ListDeSerializationTests.java @@ -1,216 +1,216 @@ -package ecologylab.fundamental; - -import static org.junit.Assert.*; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.primaryScenarioEnum; -import ecologylab.serialization.secondaryScenarioEnum; -import ecologylab.serialization.formatenums.StringFormat; - -public class ListDeSerializationTests { - - - private static SimplTypesScope ourSTS = SimplTypesScope.get("enumTestsDeSerialize", primaryScenarioEnum.class, secondaryScenarioEnum.class, - customValuedEnumerationScalar.class, basicEnumerationScalar.class, basicEnumerationList.class, basicScalarList.class, basicComposite.class, basicCompositeList.class); - @Test - public void EnumerationListsSerialize() - { - fail("You haven't picked a format yet, Tom. Pick one."); - } - - @Test - public void EnumerationListsDeserialize() throws SIMPLTranslationException - { - List ourList = new ArrayList(); - ourList.add(primaryScenarioEnum.firstValue); - ourList.add(primaryScenarioEnum.secondValue); - ourList.add(primaryScenarioEnum.thirdValue); - - basicEnumerationList bel = new basicEnumerationList(); - bel.ourList = ourList; - - StringBuilder result = ourSTS.serialize(bel, StringFormat.XML); - basicEnumerationList after = (basicEnumerationList) ourSTS.deserialize(result.toString(), StringFormat.XML); - - assertNotNull(after.ourList); - assertEquals(3, after.ourList.size()); - for(int i = 0; i < 3; i++) - { - assertEquals(bel.ourList.get(i), after.ourList.get(i)); - } - } - - - @Test - public void ScalarListsDeserializeXML() throws SIMPLTranslationException - { - testScalarListSerialization(StringFormat.XML); - } - - @Test - public void ScalarListsDeserializeJSON() throws SIMPLTranslationException - { - testScalarListSerialization(StringFormat.JSON); - } - - private void testScalarListSerialization(StringFormat format) throws SIMPLTranslationException - { - List myList = new ArrayList(); - myList.add(0); - myList.add(1); - myList.add(2); - - basicScalarList bel = new basicScalarList(); - bel.ourList = myList; - - StringBuilder result = ourSTS.serialize(bel, format); - - System.out.println(result.toString()); - - basicScalarList after = (basicScalarList) ourSTS.deserialize(result.toString(), format); - - assertNotNull(after.ourList); - assertEquals("Missing elements from the list!", 3, after.ourList.size()); - for(int i = 0; i < 3; i++) - { - assertEquals(bel.ourList.get(i), after.ourList.get(i)); - } - } - - @Test - public void basicCompositeDeserializesXML() throws SIMPLTranslationException - { - for(int i = -3; i < 4; i++) - { - testABasicComposite(i, StringFormat.XML); - } - } - - @Test - public void basicCompositeDeserializesJSON() throws SIMPLTranslationException - { - for(int i = -3; i < 4; i++) - { - testABasicComposite(i, StringFormat.JSON); - } - } - - private void testABasicComposite(int i, StringFormat format) throws SIMPLTranslationException - { - basicComposite bc = new basicComposite(i); - - assertEquals("value in bc.a was incorrect.", new Integer(i),bc.a); - assertEquals("value in bc.b was incorrect.", i+1,bc.b); - - compositeTest("basic w/ b = a+1", bc, format); - } - - - @Test - public void basicCompositeSetToProperValuesDefaultValuesWithFDSetDefault() - { - basicComposite bc = new basicComposite(); - bc.b = -1; - - assertNull(bc.a); - TranslationContext tc = new TranslationContext(); - - ClassDescriptor cd = ClassDescriptor.getClassDescriptor(bc.getClass()); - for(FieldDescriptor fd : cd.allFieldDescriptors()) - { - fd.setFieldToScalarDefault(bc, tc); - } - - assertTrue(bc.a.equals(new Integer(0))); - assertTrue(bc.b == 0); - } - - @Test - public void basicCompositesWithDefaultValuesBehaveCorrectlyXML() throws SIMPLTranslationException - { - basicCompositeTest(StringFormat.XML); - } - - @Test - public void basicCompositesWithDefaultValuesBehaveCorrectlyJSON() throws SIMPLTranslationException - { - basicCompositeTest(StringFormat.JSON); - } - - private void basicCompositeTest(StringFormat format) throws SIMPLTranslationException - { - basicComposite oneDefault = new basicComposite(); - oneDefault.a = 1; - oneDefault.b = 0; - - compositeTest("b", oneDefault, format); - - oneDefault.a = 0; - oneDefault.b = 1; - - compositeTest("a", oneDefault, format); - - basicComposite bothDefault = new basicComposite(); - bothDefault.a = 0; - bothDefault.b = 0; - - compositeTest("both", bothDefault, format); - } - - private void compositeTest(String caseDefaults, basicComposite bc, StringFormat format) throws SIMPLTranslationException - { - StringBuilder result = ourSTS.serialize(bc, format); - assertFalse("Representation should never be empty!!! Default: " + caseDefaults, result.toString().isEmpty()); - System.out.println(result.toString()); - basicComposite after = (basicComposite) ourSTS.deserialize(result.toString(), format); - - assertEquals("Values incorrect for a after roundtrip. Default: " + caseDefaults, bc.a, after.a); - assertEquals("Values incorrect for b after roundtrip. Default: " + caseDefaults, bc.b, after.b); - } - - @Test - public void CompositeListsDeserializeJSON() throws SIMPLTranslationException - { - testCompositeList(StringFormat.JSON); - } - - @Test - public void CompositeListsDeserializeXML() throws SIMPLTranslationException - { - testCompositeList(StringFormat.XML); - } - - - private void testCompositeList(StringFormat format) throws SIMPLTranslationException - { - List myList = new ArrayList(); - myList.add(new basicComposite(0)); - myList.add(new basicComposite(1)); - myList.add(new basicComposite(2)); - - basicCompositeList bel = new basicCompositeList(); - bel.ourList = myList; - - StringBuilder result = ourSTS.serialize(bel, format); - basicCompositeList after = (basicCompositeList) ourSTS.deserialize(result.toString(), format); - - assertNotNull(after.ourList); - assertEquals("Missing elements from the list!",3, after.ourList.size()); - for(int i = 0; i < 3; i++) - { - assertEquals("Values incorrect for rountrip for a: ", bel.ourList.get(i).a, after.ourList.get(i).a); - assertEquals("Values incorrect for rountrip for b: ", bel.ourList.get(i).b, after.ourList.get(i).b); - } - } -} +package ecologylab.fundamental; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.primaryScenarioEnum; +import ecologylab.serialization.secondaryScenarioEnum; +import ecologylab.serialization.formatenums.StringFormat; + +public class ListDeSerializationTests { + + + private static SimplTypesScope ourSTS = SimplTypesScope.get("enumTestsDeSerialize", primaryScenarioEnum.class, secondaryScenarioEnum.class, + customValuedEnumerationScalar.class, basicEnumerationScalar.class, basicEnumerationList.class, basicScalarList.class, basicComposite.class, basicCompositeList.class); + @Test + public void EnumerationListsSerialize() + { + fail("You haven't picked a format yet, Tom. Pick one."); + } + + @Test + public void EnumerationListsDeserialize() throws SIMPLTranslationException + { + List ourList = new ArrayList(); + ourList.add(primaryScenarioEnum.firstValue); + ourList.add(primaryScenarioEnum.secondValue); + ourList.add(primaryScenarioEnum.thirdValue); + + basicEnumerationList bel = new basicEnumerationList(); + bel.ourList = ourList; + + StringBuilder result = ourSTS.serialize(bel, StringFormat.XML); + basicEnumerationList after = (basicEnumerationList) ourSTS.deserialize(result.toString(), StringFormat.XML); + + assertNotNull(after.ourList); + assertEquals(3, after.ourList.size()); + for(int i = 0; i < 3; i++) + { + assertEquals(bel.ourList.get(i), after.ourList.get(i)); + } + } + + + @Test + public void ScalarListsDeserializeXML() throws SIMPLTranslationException + { + testScalarListSerialization(StringFormat.XML); + } + + @Test + public void ScalarListsDeserializeJSON() throws SIMPLTranslationException + { + testScalarListSerialization(StringFormat.JSON); + } + + private void testScalarListSerialization(StringFormat format) throws SIMPLTranslationException + { + List myList = new ArrayList(); + myList.add(0); + myList.add(1); + myList.add(2); + + basicScalarList bel = new basicScalarList(); + bel.ourList = myList; + + StringBuilder result = ourSTS.serialize(bel, format); + + System.out.println(result.toString()); + + basicScalarList after = (basicScalarList) ourSTS.deserialize(result.toString(), format); + + assertNotNull(after.ourList); + assertEquals("Missing elements from the list!", 3, after.ourList.size()); + for(int i = 0; i < 3; i++) + { + assertEquals(bel.ourList.get(i), after.ourList.get(i)); + } + } + + @Test + public void basicCompositeDeserializesXML() throws SIMPLTranslationException + { + for(int i = -3; i < 4; i++) + { + testABasicComposite(i, StringFormat.XML); + } + } + + @Test + public void basicCompositeDeserializesJSON() throws SIMPLTranslationException + { + for(int i = -3; i < 4; i++) + { + testABasicComposite(i, StringFormat.JSON); + } + } + + private void testABasicComposite(int i, StringFormat format) throws SIMPLTranslationException + { + basicComposite bc = new basicComposite(i); + + assertEquals("value in bc.a was incorrect.", new Integer(i),bc.a); + assertEquals("value in bc.b was incorrect.", i+1,bc.b); + + compositeTest("basic w/ b = a+1", bc, format); + } + + + @Test + public void basicCompositeSetToProperValuesDefaultValuesWithFDSetDefault() + { + basicComposite bc = new basicComposite(); + bc.b = -1; + + assertNull(bc.a); + TranslationContext tc = new TranslationContext(); + + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(bc.getClass()); + for(FieldDescriptor fd : cd.allFieldDescriptors()) + { + fd.setFieldToScalarDefault(bc, tc); + } + + assertTrue(bc.a.equals(new Integer(0))); + assertTrue(bc.b == 0); + } + + @Test + public void basicCompositesWithDefaultValuesBehaveCorrectlyXML() throws SIMPLTranslationException + { + basicCompositeTest(StringFormat.XML); + } + + @Test + public void basicCompositesWithDefaultValuesBehaveCorrectlyJSON() throws SIMPLTranslationException + { + basicCompositeTest(StringFormat.JSON); + } + + private void basicCompositeTest(StringFormat format) throws SIMPLTranslationException + { + basicComposite oneDefault = new basicComposite(); + oneDefault.a = 1; + oneDefault.b = 0; + + compositeTest("b", oneDefault, format); + + oneDefault.a = 0; + oneDefault.b = 1; + + compositeTest("a", oneDefault, format); + + basicComposite bothDefault = new basicComposite(); + bothDefault.a = 0; + bothDefault.b = 0; + + compositeTest("both", bothDefault, format); + } + + private void compositeTest(String caseDefaults, basicComposite bc, StringFormat format) throws SIMPLTranslationException + { + StringBuilder result = ourSTS.serialize(bc, format); + assertFalse("Representation should never be empty!!! Default: " + caseDefaults, result.toString().isEmpty()); + System.out.println(result.toString()); + basicComposite after = (basicComposite) ourSTS.deserialize(result.toString(), format); + + assertEquals("Values incorrect for a after roundtrip. Default: " + caseDefaults, bc.a, after.a); + assertEquals("Values incorrect for b after roundtrip. Default: " + caseDefaults, bc.b, after.b); + } + + @Test + public void CompositeListsDeserializeJSON() throws SIMPLTranslationException + { + testCompositeList(StringFormat.JSON); + } + + @Test + public void CompositeListsDeserializeXML() throws SIMPLTranslationException + { + testCompositeList(StringFormat.XML); + } + + + private void testCompositeList(StringFormat format) throws SIMPLTranslationException + { + List myList = new ArrayList(); + myList.add(new basicComposite(0)); + myList.add(new basicComposite(1)); + myList.add(new basicComposite(2)); + + basicCompositeList bel = new basicCompositeList(); + bel.ourList = myList; + + StringBuilder result = ourSTS.serialize(bel, format); + basicCompositeList after = (basicCompositeList) ourSTS.deserialize(result.toString(), format); + + assertNotNull(after.ourList); + assertEquals("Missing elements from the list!",3, after.ourList.size()); + for(int i = 0; i < 3; i++) + { + assertEquals("Values incorrect for rountrip for a: ", bel.ourList.get(i).a, after.ourList.get(i).a); + assertEquals("Values incorrect for rountrip for b: ", bel.ourList.get(i).b, after.ourList.get(i).b); + } + } +} diff --git a/simplTests/test/ecologylab/fundamental/MultiIndexerTest.java b/simplTests/test/ecologylab/fundamental/MultiIndexerTest.java index e30ac69e..f54c459f 100644 --- a/simplTests/test/ecologylab/fundamental/MultiIndexerTest.java +++ b/simplTests/test/ecologylab/fundamental/MultiIndexerTest.java @@ -1,53 +1,53 @@ -package ecologylab.fundamental; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import ecologylab.generic.MultiIndexer; -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.ClassDescriptorIndexer; - -public class MultiIndexerTest { - - @Test - public void testInsert() { - - final class myClass{ - } - - MultiIndexer> sut = new ClassDescriptorIndexer(); - - ClassDescriptor relevant = ClassDescriptor.getClassDescriptor(myClass.class); - - sut.Insert(relevant); - - ClassDescriptor result = sut.by("simplname").get(relevant.getClassSimpleName()); - - assertEquals(relevant, result); - assertTrue(1==sut.size()); - - - } - - @Test - public void testRemove() - { - final class myClass{} - - MultiIndexer> sut = new ClassDescriptorIndexer(); - - ClassDescriptor relevant = ClassDescriptor.getClassDescriptor(myClass.class); - - sut.Insert(relevant); - - assertTrue(1==sut.size()); - - sut.Remove(relevant); - - assertTrue(0==sut.size()); - - assertNull(sut.by("simplname").get(relevant.getClassSimpleName())); - } - -} +package ecologylab.fundamental; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import ecologylab.generic.MultiIndexer; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.ClassDescriptorIndexer; + +public class MultiIndexerTest { + + @Test + public void testInsert() { + + final class myClass{ + } + + MultiIndexer> sut = new ClassDescriptorIndexer(); + + ClassDescriptor relevant = ClassDescriptor.getClassDescriptor(myClass.class); + + sut.Insert(relevant); + + ClassDescriptor result = sut.by("simplname").get(relevant.getClassSimpleName()); + + assertEquals(relevant, result); + assertTrue(1==sut.size()); + + + } + + @Test + public void testRemove() + { + final class myClass{} + + MultiIndexer> sut = new ClassDescriptorIndexer(); + + ClassDescriptor relevant = ClassDescriptor.getClassDescriptor(myClass.class); + + sut.Insert(relevant); + + assertTrue(1==sut.size()); + + sut.Remove(relevant); + + assertTrue(0==sut.size()); + + assertNull(sut.by("simplname").get(relevant.getClassSimpleName())); + } + +} diff --git a/simplTests/test/ecologylab/fundamental/RoundtripTestsProvisional.java b/simplTests/test/ecologylab/fundamental/RoundtripTestsProvisional.java index a3daa634..8eed9fe8 100644 --- a/simplTests/test/ecologylab/fundamental/RoundtripTestsProvisional.java +++ b/simplTests/test/ecologylab/fundamental/RoundtripTestsProvisional.java @@ -1,102 +1,102 @@ -package ecologylab.fundamental; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.formatenums.StringFormat; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.TypeRegistry; - -public class RoundtripTestsProvisional { - - @Test - public void testJSONRoundtripWithTrickyString() throws SIMPLTranslationException { - - - TrickyString ts = new TrickyString(); - ts.trickyString = "\" \\ / // <<< >>> {}{}{} {>>> == =:: / / / /_ -- --__ : : \b a \f b \n c \n d \r e \t f"; // we choke on unicode, for now \u1337"; - System.out.println(ts.trickyString); - - StringBuilder serialized = SimplTypesScope.serialize(ts, StringFormat.JSON); - System.out.println(serialized.toString()); - - SimplTypesScope sts = SimplTypesScope.get("stringTest", TrickyString.class); - - Object result = sts.deserialize(serialized.toString(), StringFormat.JSON); - assertTrue(result.getClass().equals(TrickyString.class)); - TrickyString otherString = (TrickyString)result; - - System.out.println(otherString.trickyString); - - assertEquals(ts.trickyString, otherString.trickyString); - } - - @Test - public void testXMLRoundtripWithTrickyString() throws SIMPLTranslationException { - - - TrickyString ts = new TrickyString(); - ts.trickyString = "< >> <<<<< >>>> ><<><><>< \"/ '' = = = = ;: === \": ' \\\"\\\"\\\\\" '\" \\ / // / / / /_ -- --__ : : \b a \f b \n c \n d \r e \t f"; //We choke on unicode, for now. \u1337"; - System.out.println(ts.trickyString); - - StringBuilder serialized = SimplTypesScope.serialize(ts, StringFormat.XML); - System.out.println(serialized.toString()); - - SimplTypesScope sts = SimplTypesScope.get("stringTest", TrickyString.class); - - Object result = sts.deserialize(serialized.toString(), StringFormat.XML); - assertTrue(result.getClass().equals(TrickyString.class)); - TrickyString otherString = (TrickyString)result; - - System.out.println(otherString.trickyString); - - assertEquals(ts.trickyString, otherString.trickyString); - } - - - @Test - public void TestSimplStringScalarTypeSetsDefaultToNull() - { - TrickyString ts = new TrickyString(); - ts.trickyString = "totallyNotDefault"; - - ClassDescriptor cd = ClassDescriptor.getClassDescriptor(TrickyString.class); - - FieldDescriptor fd = cd.allFieldDescriptors().get(0); - TranslationContext tc = null; - fd.setFieldToScalarDefault(ts, tc); - - assertEquals("Should have changed!", null, ts.trickyString); - - } - - @Test - public void nullStringValue() throws SIMPLTranslationException, IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException - { - TrickyString ts = new TrickyString(); - ts.trickyString = null; - - ScalarType stringType = TypeRegistry.getScalarType(String.class); - - assertTrue("Null is the new default string value - via value check", stringType.isDefaultValue(ts.trickyString)); - assertTrue("Null is the new default string value - via field check", stringType.isDefaultValue(ts.getClass().getField("trickyString"), ts)); - - String xml = SimplTypesScope.serialize(ts, StringFormat.XML).toString(); - System.out.println(xml); - - SimplTypesScope typeScope = SimplTypesScope.get("TrickyString", TrickyString.class); - TrickyString ts1 = (TrickyString) typeScope.deserialize(xml, StringFormat.XML); - assertNotNull("Expecting an object back!", ts1); - - assertEquals("Expecting null value back!",null, ts1.trickyString); - } - - - -} +package ecologylab.fundamental; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.formatenums.StringFormat; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.TypeRegistry; + +public class RoundtripTestsProvisional { + + @Test + public void testJSONRoundtripWithTrickyString() throws SIMPLTranslationException { + + + TrickyString ts = new TrickyString(); + ts.trickyString = "\" \\ / // <<< >>> {}{}{} {>>> == =:: / / / /_ -- --__ : : \b a \f b \n c \n d \r e \t f"; // we choke on unicode, for now \u1337"; + System.out.println(ts.trickyString); + + StringBuilder serialized = SimplTypesScope.serialize(ts, StringFormat.JSON); + System.out.println(serialized.toString()); + + SimplTypesScope sts = SimplTypesScope.get("stringTest", TrickyString.class); + + Object result = sts.deserialize(serialized.toString(), StringFormat.JSON); + assertTrue(result.getClass().equals(TrickyString.class)); + TrickyString otherString = (TrickyString)result; + + System.out.println(otherString.trickyString); + + assertEquals(ts.trickyString, otherString.trickyString); + } + + @Test + public void testXMLRoundtripWithTrickyString() throws SIMPLTranslationException { + + + TrickyString ts = new TrickyString(); + ts.trickyString = "< >> <<<<< >>>> ><<><><>< \"/ '' = = = = ;: === \": ' \\\"\\\"\\\\\" '\" \\ / // / / / /_ -- --__ : : \b a \f b \n c \n d \r e \t f"; //We choke on unicode, for now. \u1337"; + System.out.println(ts.trickyString); + + StringBuilder serialized = SimplTypesScope.serialize(ts, StringFormat.XML); + System.out.println(serialized.toString()); + + SimplTypesScope sts = SimplTypesScope.get("stringTest", TrickyString.class); + + Object result = sts.deserialize(serialized.toString(), StringFormat.XML); + assertTrue(result.getClass().equals(TrickyString.class)); + TrickyString otherString = (TrickyString)result; + + System.out.println(otherString.trickyString); + + assertEquals(ts.trickyString, otherString.trickyString); + } + + + @Test + public void TestSimplStringScalarTypeSetsDefaultToNull() + { + TrickyString ts = new TrickyString(); + ts.trickyString = "totallyNotDefault"; + + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(TrickyString.class); + + FieldDescriptor fd = cd.allFieldDescriptors().get(0); + TranslationContext tc = null; + fd.setFieldToScalarDefault(ts, tc); + + assertEquals("Should have changed!", null, ts.trickyString); + + } + + @Test + public void nullStringValue() throws SIMPLTranslationException, IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException + { + TrickyString ts = new TrickyString(); + ts.trickyString = null; + + ScalarType stringType = TypeRegistry.getScalarType(String.class); + + assertTrue("Null is the new default string value - via value check", stringType.isDefaultValue(ts.trickyString)); + assertTrue("Null is the new default string value - via field check", stringType.isDefaultValue(ts.getClass().getField("trickyString"), ts)); + + String xml = SimplTypesScope.serialize(ts, StringFormat.XML).toString(); + System.out.println(xml); + + SimplTypesScope typeScope = SimplTypesScope.get("TrickyString", TrickyString.class); + TrickyString ts1 = (TrickyString) typeScope.deserialize(xml, StringFormat.XML); + assertNotNull("Expecting an object back!", ts1); + + assertEquals("Expecting null value back!",null, ts1.trickyString); + } + + + +} diff --git a/simplTests/test/ecologylab/fundamental/SimplTypesScopeTest.java b/simplTests/test/ecologylab/fundamental/SimplTypesScopeTest.java index ee197bab..e332586d 100644 --- a/simplTests/test/ecologylab/fundamental/SimplTypesScopeTest.java +++ b/simplTests/test/ecologylab/fundamental/SimplTypesScopeTest.java @@ -1,13 +1,13 @@ -package ecologylab.fundamental; - -import static org.junit.Assert.*; - -import org.junit.Test; - -public class SimplTypesScopeTest { - - @Test - public void test() { - } - -} +package ecologylab.fundamental; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class SimplTypesScopeTest { + + @Test + public void test() { + } + +} diff --git a/simplTests/test/ecologylab/fundamental/TrickyString.java b/simplTests/test/ecologylab/fundamental/TrickyString.java index 3a4333ab..c23cfac8 100644 --- a/simplTests/test/ecologylab/fundamental/TrickyString.java +++ b/simplTests/test/ecologylab/fundamental/TrickyString.java @@ -1,24 +1,24 @@ -package ecologylab.fundamental; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import org.junit.Test; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.StringFormat; -import ecologylab.serialization.types.ScalarType; -import ecologylab.serialization.types.TypeRegistry; - -public class TrickyString -{ - @simpl_scalar - public String trickyString; - - public TrickyString(){} - - - -} +package ecologylab.fundamental; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import org.junit.Test; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.StringFormat; +import ecologylab.serialization.types.ScalarType; +import ecologylab.serialization.types.TypeRegistry; + +public class TrickyString +{ + @simpl_scalar + public String trickyString; + + public TrickyString(){} + + + +} diff --git a/simplTests/test/ecologylab/fundamental/ValidateSimplScalarTestMechanism.java b/simplTests/test/ecologylab/fundamental/ValidateSimplScalarTestMechanism.java index 0da636e8..90ddbf99 100644 --- a/simplTests/test/ecologylab/fundamental/ValidateSimplScalarTestMechanism.java +++ b/simplTests/test/ecologylab/fundamental/ValidateSimplScalarTestMechanism.java @@ -1,12 +1,12 @@ -package ecologylab.fundamental; - -import org.junit.Test; - -public class ValidateSimplScalarTestMechanism { - - @Test - public void IteratesThroughAllTestClasses() - { - - } -} +package ecologylab.fundamental; + +import org.junit.Test; + +public class ValidateSimplScalarTestMechanism { + + @Test + public void IteratesThroughAllTestClasses() + { + + } +} diff --git a/simplTests/test/ecologylab/fundamental/basicComposite.java b/simplTests/test/ecologylab/fundamental/basicComposite.java index 931463db..5ba84648 100644 --- a/simplTests/test/ecologylab/fundamental/basicComposite.java +++ b/simplTests/test/ecologylab/fundamental/basicComposite.java @@ -1,19 +1,19 @@ -package ecologylab.fundamental; - -import ecologylab.serialization.annotations.simpl_scalar; - -public class basicComposite { - - @simpl_scalar - public Integer a; - @simpl_scalar - public int b; - - public basicComposite(){} - - public basicComposite(int i) - { - this.a = i; - this.b = i+1; - } -} +package ecologylab.fundamental; + +import ecologylab.serialization.annotations.simpl_scalar; + +public class basicComposite { + + @simpl_scalar + public Integer a; + @simpl_scalar + public int b; + + public basicComposite(){} + + public basicComposite(int i) + { + this.a = i; + this.b = i+1; + } +} diff --git a/simplTests/test/ecologylab/fundamental/basicCompositeList.java b/simplTests/test/ecologylab/fundamental/basicCompositeList.java index 9461812f..84797dd7 100644 --- a/simplTests/test/ecologylab/fundamental/basicCompositeList.java +++ b/simplTests/test/ecologylab/fundamental/basicCompositeList.java @@ -1,17 +1,17 @@ -package ecologylab.fundamental; - -import java.util.ArrayList; -import java.util.List; - -import ecologylab.serialization.annotations.simpl_collection; - -public class basicCompositeList { - - @simpl_collection("collect") - public List ourList; - - public basicCompositeList() - { - ourList = new ArrayList(); - } -} +package ecologylab.fundamental; + +import java.util.ArrayList; +import java.util.List; + +import ecologylab.serialization.annotations.simpl_collection; + +public class basicCompositeList { + + @simpl_collection("collect") + public List ourList; + + public basicCompositeList() + { + ourList = new ArrayList(); + } +} diff --git a/simplTests/test/ecologylab/fundamental/basicEnumerationList.java b/simplTests/test/ecologylab/fundamental/basicEnumerationList.java index 081c41cc..37c12b7d 100644 --- a/simplTests/test/ecologylab/fundamental/basicEnumerationList.java +++ b/simplTests/test/ecologylab/fundamental/basicEnumerationList.java @@ -1,17 +1,17 @@ -package ecologylab.fundamental; - -import java.util.ArrayList; -import java.util.List; - -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.primaryScenarioEnum; - - - -public class basicEnumerationList { - - @simpl_collection("collect") - public List ourList; - - public basicEnumerationList(){ ourList = new ArrayList(); } -} +package ecologylab.fundamental; + +import java.util.ArrayList; +import java.util.List; + +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.primaryScenarioEnum; + + + +public class basicEnumerationList { + + @simpl_collection("collect") + public List ourList; + + public basicEnumerationList(){ ourList = new ArrayList(); } +} diff --git a/simplTests/test/ecologylab/fundamental/basicEnumerationScalar.java b/simplTests/test/ecologylab/fundamental/basicEnumerationScalar.java index 65902bbf..9a3b176e 100644 --- a/simplTests/test/ecologylab/fundamental/basicEnumerationScalar.java +++ b/simplTests/test/ecologylab/fundamental/basicEnumerationScalar.java @@ -1,12 +1,12 @@ -package ecologylab.fundamental; - -import ecologylab.serialization.primaryScenarioEnum; -import ecologylab.serialization.annotations.simpl_scalar; - -final class basicEnumerationScalar -{ - @simpl_scalar - public primaryScenarioEnum ourEnum; - - public basicEnumerationScalar(){}; +package ecologylab.fundamental; + +import ecologylab.serialization.primaryScenarioEnum; +import ecologylab.serialization.annotations.simpl_scalar; + +final class basicEnumerationScalar +{ + @simpl_scalar + public primaryScenarioEnum ourEnum; + + public basicEnumerationScalar(){}; } \ No newline at end of file diff --git a/simplTests/test/ecologylab/fundamental/basicScalarList.java b/simplTests/test/ecologylab/fundamental/basicScalarList.java index ced94343..bdf6618a 100644 --- a/simplTests/test/ecologylab/fundamental/basicScalarList.java +++ b/simplTests/test/ecologylab/fundamental/basicScalarList.java @@ -1,17 +1,17 @@ -package ecologylab.fundamental; - -import java.util.ArrayList; -import java.util.List; - -import ecologylab.serialization.annotations.simpl_collection; - -public class basicScalarList { - - @simpl_collection("collect") - public List ourList; - - public basicScalarList() - { - ourList = new ArrayList(); - } -} +package ecologylab.fundamental; + +import java.util.ArrayList; +import java.util.List; + +import ecologylab.serialization.annotations.simpl_collection; + +public class basicScalarList { + + @simpl_collection("collect") + public List ourList; + + public basicScalarList() + { + ourList = new ArrayList(); + } +} diff --git a/simplTests/test/ecologylab/fundamental/customValuedEnumerationScalar.java b/simplTests/test/ecologylab/fundamental/customValuedEnumerationScalar.java index 77f2b257..c56a01a7 100644 --- a/simplTests/test/ecologylab/fundamental/customValuedEnumerationScalar.java +++ b/simplTests/test/ecologylab/fundamental/customValuedEnumerationScalar.java @@ -1,15 +1,15 @@ -package ecologylab.fundamental; - -import ecologylab.serialization.secondaryScenarioEnum; -import ecologylab.serialization.annotations.simpl_scalar; - -final class customValuedEnumerationScalar -{ - @simpl_scalar - public secondaryScenarioEnum ourEnum; - - public customValuedEnumerationScalar() - { - - } +package ecologylab.fundamental; + +import ecologylab.serialization.secondaryScenarioEnum; +import ecologylab.serialization.annotations.simpl_scalar; + +final class customValuedEnumerationScalar +{ + @simpl_scalar + public secondaryScenarioEnum ourEnum; + + public customValuedEnumerationScalar() + { + + } } \ No newline at end of file diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleBoolean.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleBoolean.java index cd6963d8..243bf07f 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleBoolean.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleBoolean.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleBoolean { - @simpl_scalar - private Boolean simpleboolean; - - public Boolean getSimpleBoolean(){ - return this.simpleboolean; - } - - public void setSimpleBoolean(Boolean value){ - this.simpleboolean = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleBoolean { + @simpl_scalar + private Boolean simpleboolean; + + public Boolean getSimpleBoolean(){ + return this.simpleboolean; + } + + public void setSimpleBoolean(Boolean value){ + this.simpleboolean = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleByte.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleByte.java index 17d3e562..077e74a5 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleByte.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleByte.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleByte { - @simpl_scalar - private Byte simplebyte; - - public Byte getSimpleByte(){ - return this.simplebyte; - } - - public void setSimpleByte(Byte value){ - this.simplebyte = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleByte { + @simpl_scalar + private Byte simplebyte; + + public Byte getSimpleByte(){ + return this.simplebyte; + } + + public void setSimpleByte(Byte value){ + this.simplebyte = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleChar.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleChar.java index a2472ecd..0bb4ecf8 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleChar.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleChar.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleChar { - @simpl_scalar - private Character simplechar; - - public Character getSimpleChar(){ - return this.simplechar; - } - - public void setSimpleChar(Character value){ - this.simplechar = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleChar { + @simpl_scalar + private Character simplechar; + + public Character getSimpleChar(){ + return this.simplechar; + } + + public void setSimpleChar(Character value){ + this.simplechar = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleDate.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleDate.java index 2a27e06d..15f1f99c 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleDate.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleDate.java @@ -1,15 +1,15 @@ -package ecologylab.fundamental.simplescalar; -import java.util.Date; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleDate { - @simpl_scalar - private Date simpledate; - - public Date getSimpleDate(){ - return this.simpledate; - } - - public void setSimpleDate(Date value){ - this.simpledate = value; - } -} +package ecologylab.fundamental.simplescalar; +import java.util.Date; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleDate { + @simpl_scalar + private Date simpledate; + + public Date getSimpleDate(){ + return this.simpledate; + } + + public void setSimpleDate(Date value){ + this.simpledate = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleDouble.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleDouble.java index 926963b0..6120703a 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleDouble.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleDouble.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleDouble { - @simpl_scalar - private Double simpledouble; - - public Double getSimpleDouble(){ - return this.simpledouble; - } - - public void setSimpleDouble(Double value){ - this.simpledouble = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleDouble { + @simpl_scalar + private Double simpledouble; + + public Double getSimpleDouble(){ + return this.simpledouble; + } + + public void setSimpleDouble(Double value){ + this.simpledouble = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleFloat.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleFloat.java index 7dc263e6..2716b374 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleFloat.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleFloat.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleFloat { - @simpl_scalar - private Float simplefloat; - - public Float getSimpleFloat(){ - return this.simplefloat; - } - - public void setSimpleFloat(Float value){ - this.simplefloat = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleFloat { + @simpl_scalar + private Float simplefloat; + + public Float getSimpleFloat(){ + return this.simplefloat; + } + + public void setSimpleFloat(Float value){ + this.simplefloat = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleInteger.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleInteger.java index 356b143f..07d8e387 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleInteger.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleInteger.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleInteger { - @simpl_scalar - private Integer simpleinteger; - - public Integer getSimpleInteger(){ - return this.simpleinteger; - } - - public void setSimpleInteger(Integer value){ - this.simpleinteger = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleInteger { + @simpl_scalar + private Integer simpleinteger; + + public Integer getSimpleInteger(){ + return this.simpleinteger; + } + + public void setSimpleInteger(Integer value){ + this.simpleinteger = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleJavaURL.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleJavaURL.java index 24d55e3f..3e3c93e2 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleJavaURL.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleJavaURL.java @@ -1,15 +1,15 @@ -package ecologylab.fundamental.simplescalar; -import java.net.URL; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleJavaURL { - @simpl_scalar - private URL simplejavaurl; - - public URL getSimpleJavaURL(){ - return this.simplejavaurl; - } - - public void setSimpleJavaURL(URL value){ - this.simplejavaurl = value; - } -} +package ecologylab.fundamental.simplescalar; +import java.net.URL; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleJavaURL { + @simpl_scalar + private URL simplejavaurl; + + public URL getSimpleJavaURL(){ + return this.simplejavaurl; + } + + public void setSimpleJavaURL(URL value){ + this.simplejavaurl = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleLong.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleLong.java index b5f9c6da..b9c609ce 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleLong.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleLong.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleLong { - @simpl_scalar - private Long simplelong; - - public Long getSimpleLong(){ - return this.simplelong; - } - - public void setSimpleLong(Long value){ - this.simplelong = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleLong { + @simpl_scalar + private Long simplelong; + + public Long getSimpleLong(){ + return this.simplelong; + } + + public void setSimpleLong(Long value){ + this.simplelong = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleParsedURL.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleParsedURL.java index 8e07e4a0..3b9d6945 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleParsedURL.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleParsedURL.java @@ -1,15 +1,15 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleParsedURL { - @simpl_scalar - private ParsedURL simpleparsedurl; - - public ParsedURL getSimpleParsedURL(){ - return this.simpleparsedurl; - } - - public void setSimpleParsedURL(ParsedURL value){ - this.simpleparsedurl = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleParsedURL { + @simpl_scalar + private ParsedURL simpleparsedurl; + + public ParsedURL getSimpleParsedURL(){ + return this.simpleparsedurl; + } + + public void setSimpleParsedURL(ParsedURL value){ + this.simpleparsedurl = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimplePattern.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimplePattern.java index 6d25b31f..5463dd2e 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimplePattern.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimplePattern.java @@ -1,15 +1,15 @@ -package ecologylab.fundamental.simplescalar; -import java.util.regex.Pattern; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimplePattern { - @simpl_scalar - private Pattern simplepattern; - - public Pattern getSimplePattern(){ - return this.simplepattern; - } - - public void setSimplePattern(Pattern value){ - this.simplepattern = value; - } -} +package ecologylab.fundamental.simplescalar; +import java.util.regex.Pattern; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimplePattern { + @simpl_scalar + private Pattern simplepattern; + + public Pattern getSimplePattern(){ + return this.simplepattern; + } + + public void setSimplePattern(Pattern value){ + this.simplepattern = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleShort.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleShort.java index 75a6c859..c32fb47d 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleShort.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleShort.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleShort { - @simpl_scalar - private Short simpleshort; - - public Short getSimpleShort(){ - return this.simpleshort; - } - - public void setSimpleShort(Short value){ - this.simpleshort = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleShort { + @simpl_scalar + private Short simpleshort; + + public Short getSimpleShort(){ + return this.simpleshort; + } + + public void setSimpleShort(Short value){ + this.simpleshort = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleString.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleString.java index 8a1a84cd..1ed67de3 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleString.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleString.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleString { - @simpl_scalar - private String simplestring; - - public String getSimpleString(){ - return this.simplestring; - } - - public void setSimpleString(String value){ - this.simplestring = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleString { + @simpl_scalar + private String simplestring; + + public String getSimpleString(){ + return this.simplestring; + } + + public void setSimpleString(String value){ + this.simplestring = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleStringBuilder.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleStringBuilder.java index ad4ea721..0af855a2 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleStringBuilder.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleStringBuilder.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleStringBuilder { - @simpl_scalar - private StringBuilder simplestringbuilder; - - public StringBuilder getSimpleStringBuilder(){ - return this.simplestringbuilder; - } - - public void setSimpleStringBuilder(StringBuilder value){ - this.simplestringbuilder = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleStringBuilder { + @simpl_scalar + private StringBuilder simplestringbuilder; + + public StringBuilder getSimpleStringBuilder(){ + return this.simplestringbuilder; + } + + public void setSimpleStringBuilder(StringBuilder value){ + this.simplestringbuilder = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleUUID.java b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleUUID.java index 5990df21..71ed8f76 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/SimpleUUID.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/SimpleUUID.java @@ -1,15 +1,15 @@ -package ecologylab.fundamental.simplescalar; -import java.util.UUID; -import ecologylab.serialization.annotations.simpl_scalar; -public class SimpleUUID { - @simpl_scalar - private UUID simpleuuid; - - public UUID getSimpleUUID(){ - return this.simpleuuid; - } - - public void setSimpleUUID(UUID value){ - this.simpleuuid = value; - } -} +package ecologylab.fundamental.simplescalar; +import java.util.UUID; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleUUID { + @simpl_scalar + private UUID simpleuuid; + + public UUID getSimpleUUID(){ + return this.simpleuuid; + } + + public void setSimpleUUID(UUID value){ + this.simpleuuid = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimboolean.java b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimboolean.java index 468b6fd8..74a1b6ac 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimboolean.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimboolean.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class Simpleprimboolean { - @simpl_scalar - private boolean simpleprimboolean; - - public boolean getSimpleprimboolean(){ - return this.simpleprimboolean; - } - - public void setSimpleprimboolean(boolean value){ - this.simpleprimboolean = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimboolean { + @simpl_scalar + private boolean simpleprimboolean; + + public boolean getSimpleprimboolean(){ + return this.simpleprimboolean; + } + + public void setSimpleprimboolean(boolean value){ + this.simpleprimboolean = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimbyte.java b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimbyte.java index 2d58ae23..503d56cf 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimbyte.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimbyte.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class Simpleprimbyte { - @simpl_scalar - private byte simpleprimbyte; - - public byte getSimpleprimbyte(){ - return this.simpleprimbyte; - } - - public void setSimpleprimbyte(byte value){ - this.simpleprimbyte = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimbyte { + @simpl_scalar + private byte simpleprimbyte; + + public byte getSimpleprimbyte(){ + return this.simpleprimbyte; + } + + public void setSimpleprimbyte(byte value){ + this.simpleprimbyte = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimchar.java b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimchar.java index 5a77b7d4..a3f2f801 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimchar.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimchar.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class Simpleprimchar { - @simpl_scalar - private char simpleprimchar; - - public char getSimpleprimchar(){ - return this.simpleprimchar; - } - - public void setSimpleprimchar(char value){ - this.simpleprimchar = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimchar { + @simpl_scalar + private char simpleprimchar; + + public char getSimpleprimchar(){ + return this.simpleprimchar; + } + + public void setSimpleprimchar(char value){ + this.simpleprimchar = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimdouble.java b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimdouble.java index 1f8c4a6b..4adfb88a 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimdouble.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimdouble.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class Simpleprimdouble { - @simpl_scalar - private double simpleprimdouble; - - public double getSimpleprimdouble(){ - return this.simpleprimdouble; - } - - public void setSimpleprimdouble(double value){ - this.simpleprimdouble = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimdouble { + @simpl_scalar + private double simpleprimdouble; + + public double getSimpleprimdouble(){ + return this.simpleprimdouble; + } + + public void setSimpleprimdouble(double value){ + this.simpleprimdouble = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimfloat.java b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimfloat.java index d5b3197f..de3cf887 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimfloat.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimfloat.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class Simpleprimfloat { - @simpl_scalar - private float simpleprimfloat; - - public float getSimpleprimfloat(){ - return this.simpleprimfloat; - } - - public void setSimpleprimfloat(float value){ - this.simpleprimfloat = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimfloat { + @simpl_scalar + private float simpleprimfloat; + + public float getSimpleprimfloat(){ + return this.simpleprimfloat; + } + + public void setSimpleprimfloat(float value){ + this.simpleprimfloat = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimint.java b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimint.java index 37a8c54f..64c04b4f 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimint.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimint.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class Simpleprimint { - @simpl_scalar - private int simpleprimint; - - public int getSimpleprimint(){ - return this.simpleprimint; - } - - public void setSimpleprimint(int value){ - this.simpleprimint = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimint { + @simpl_scalar + private int simpleprimint; + + public int getSimpleprimint(){ + return this.simpleprimint; + } + + public void setSimpleprimint(int value){ + this.simpleprimint = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimlong.java b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimlong.java index 0624176a..5114673e 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimlong.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimlong.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class Simpleprimlong { - @simpl_scalar - private long simpleprimlong; - - public long getSimpleprimlong(){ - return this.simpleprimlong; - } - - public void setSimpleprimlong(long value){ - this.simpleprimlong = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimlong { + @simpl_scalar + private long simpleprimlong; + + public long getSimpleprimlong(){ + return this.simpleprimlong; + } + + public void setSimpleprimlong(long value){ + this.simpleprimlong = value; + } +} diff --git a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimshort.java b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimshort.java index a6596e70..fc4657d6 100644 --- a/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimshort.java +++ b/simplTests/test/ecologylab/fundamental/simplescalar/Simpleprimshort.java @@ -1,14 +1,14 @@ -package ecologylab.fundamental.simplescalar; -import ecologylab.serialization.annotations.simpl_scalar; -public class Simpleprimshort { - @simpl_scalar - private short simpleprimshort; - - public short getSimpleprimshort(){ - return this.simpleprimshort; - } - - public void setSimpleprimshort(short value){ - this.simpleprimshort = value; - } -} +package ecologylab.fundamental.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimshort { + @simpl_scalar + private short simpleprimshort; + + public short getSimpleprimshort(){ + return this.simpleprimshort; + } + + public void setSimpleprimshort(short value){ + this.simpleprimshort = value; + } +} diff --git a/simplTests/test/legacy/tests/DualBufferOutputStream.java b/simplTests/test/legacy/tests/DualBufferOutputStream.java index 3f5e857d..93066dec 100644 --- a/simplTests/test/legacy/tests/DualBufferOutputStream.java +++ b/simplTests/test/legacy/tests/DualBufferOutputStream.java @@ -1,34 +1,34 @@ -package legacy.tests; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * Dual buffer to store data as string and array of bytes. - * not efficient, just used to output data on console. - * @author nabeel - */ -public class DualBufferOutputStream extends OutputStream -{ - private StringBuilder sb = new StringBuilder(); - private ByteArrayOutputStream bs = new ByteArrayOutputStream(); - - @Override - public void write(int b) throws IOException - { - sb.append((char) b); - bs.write((byte) b); - } - - public String toString() - { - return sb.toString(); - } - - public byte[] toByte() - { - return this.bs.toByteArray(); - } - -} +package legacy.tests; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Dual buffer to store data as string and array of bytes. + * not efficient, just used to output data on console. + * @author nabeel + */ +public class DualBufferOutputStream extends OutputStream +{ + private StringBuilder sb = new StringBuilder(); + private ByteArrayOutputStream bs = new ByteArrayOutputStream(); + + @Override + public void write(int b) throws IOException + { + sb.append((char) b); + bs.write((byte) b); + } + + public String toString() + { + return sb.toString(); + } + + public byte[] toByte() + { + return this.bs.toByteArray(); + } + +} diff --git a/simplTests/test/legacy/tests/RunTests.java b/simplTests/test/legacy/tests/RunTests.java index b5ccc2c8..cf75ed97 100644 --- a/simplTests/test/legacy/tests/RunTests.java +++ b/simplTests/test/legacy/tests/RunTests.java @@ -1,104 +1,104 @@ -package legacy.tests; - -import java.util.ArrayList; - -import legacy.tests.circle.Circle; -import legacy.tests.circle.CollectionOfCircles; -import legacy.tests.circle.Point; -import legacy.tests.configuration.Configuration; -import legacy.tests.graph.ClassA; -import legacy.tests.graph.ClassB; -import legacy.tests.graph.collections.Container; -import legacy.tests.graph.diamond.ClassD; -import legacy.tests.maps.TestingMapsWithinMaps; -import legacy.tests.net.ParsedURLMapTest; -import legacy.tests.person.Faculty; -import legacy.tests.person.Person; -import legacy.tests.person.PersonDirectory; -import legacy.tests.person.Student; -import legacy.tests.person.StudentDirectory; -import legacy.tests.rss.Rss; -import legacy.tests.scalar.ScalarCollection; - - -public class RunTests -{ - private ArrayList testCases = new ArrayList(); - - public RunTests() - { - // composite - testCases.add(new Point()); - testCases.add(new Circle()); - - // collection of composite - testCases.add(new CollectionOfCircles()); - - // composite inheritence - testCases.add(new Person()); - testCases.add(new Faculty()); - testCases.add(new Student()); - testCases.add(new Rss()); - - // mono-morphic collection - testCases.add(new StudentDirectory()); - - // polymorphic collection - testCases.add(new PersonDirectory()); - testCases.add(new Configuration()); - - // graph - testCases.add(new ClassA()); - testCases.add(new ClassB()); - testCases.add(new ClassD()); - testCases.add(new Container()); - - // scalar collection - testCases.add(new ScalarCollection()); - - // maps - testCases.add(new TestingMapsWithinMaps()); - - //parsedurl - testCases.add(new ParsedURLMapTest()); - } - - public void runTestCases() - { - System.out.println("***** Executing " + testCases.size() + " Test Cases ******** "); - System.out.println(); - - int i = 0; - int fail = 0; - - for (TestCase testCase : testCases) - { - try - { - System.out - .println("--------------------------------------------------------------------------------------------------------------------------------------------------"); - System.out.println("Test Case " + ++i + " : " + testCase.getClass().getCanonicalName()); - System.out - .println("--------------------------------------------------------------------------------------------------------------------------------------------------"); - testCase.runTest(); - } - catch (Exception ex) - { - System.out.println(); - System.out.println(); - ex.printStackTrace(); - System.out.println(); - fail++; - } - } - - System.out.println(); - System.out.println("***** End: " + fail + " of " + i + " tests failed ********"); - } - - public static void main(String[] args) - { - RunTests runTests = new RunTests(); - runTests.runTestCases(); - } -} +package legacy.tests; + +import java.util.ArrayList; + +import legacy.tests.circle.Circle; +import legacy.tests.circle.CollectionOfCircles; +import legacy.tests.circle.Point; +import legacy.tests.configuration.Configuration; +import legacy.tests.graph.ClassA; +import legacy.tests.graph.ClassB; +import legacy.tests.graph.collections.Container; +import legacy.tests.graph.diamond.ClassD; +import legacy.tests.maps.TestingMapsWithinMaps; +import legacy.tests.net.ParsedURLMapTest; +import legacy.tests.person.Faculty; +import legacy.tests.person.Person; +import legacy.tests.person.PersonDirectory; +import legacy.tests.person.Student; +import legacy.tests.person.StudentDirectory; +import legacy.tests.rss.Rss; +import legacy.tests.scalar.ScalarCollection; + + +public class RunTests +{ + private ArrayList testCases = new ArrayList(); + + public RunTests() + { + // composite + testCases.add(new Point()); + testCases.add(new Circle()); + + // collection of composite + testCases.add(new CollectionOfCircles()); + + // composite inheritence + testCases.add(new Person()); + testCases.add(new Faculty()); + testCases.add(new Student()); + testCases.add(new Rss()); + + // mono-morphic collection + testCases.add(new StudentDirectory()); + + // polymorphic collection + testCases.add(new PersonDirectory()); + testCases.add(new Configuration()); + + // graph + testCases.add(new ClassA()); + testCases.add(new ClassB()); + testCases.add(new ClassD()); + testCases.add(new Container()); + + // scalar collection + testCases.add(new ScalarCollection()); + + // maps + testCases.add(new TestingMapsWithinMaps()); + + //parsedurl + testCases.add(new ParsedURLMapTest()); + } + + public void runTestCases() + { + System.out.println("***** Executing " + testCases.size() + " Test Cases ******** "); + System.out.println(); + + int i = 0; + int fail = 0; + + for (TestCase testCase : testCases) + { + try + { + System.out + .println("--------------------------------------------------------------------------------------------------------------------------------------------------"); + System.out.println("Test Case " + ++i + " : " + testCase.getClass().getCanonicalName()); + System.out + .println("--------------------------------------------------------------------------------------------------------------------------------------------------"); + testCase.runTest(); + } + catch (Exception ex) + { + System.out.println(); + System.out.println(); + ex.printStackTrace(); + System.out.println(); + fail++; + } + } + + System.out.println(); + System.out.println("***** End: " + fail + " of " + i + " tests failed ********"); + } + + public static void main(String[] args) + { + RunTests runTests = new RunTests(); + runTests.runTestCases(); + } +} diff --git a/simplTests/test/legacy/tests/TestCase.java b/simplTests/test/legacy/tests/TestCase.java index 8f05f380..4e99c8c1 100644 --- a/simplTests/test/legacy/tests/TestCase.java +++ b/simplTests/test/legacy/tests/TestCase.java @@ -1,8 +1,8 @@ -package legacy.tests; - -import ecologylab.serialization.SIMPLTranslationException; - -public interface TestCase -{ - void runTest() throws SIMPLTranslationException; -} +package legacy.tests; + +import ecologylab.serialization.SIMPLTranslationException; + +public interface TestCase +{ + void runTest() throws SIMPLTranslationException; +} diff --git a/simplTests/test/legacy/tests/TestingUtils.java b/simplTests/test/legacy/tests/TestingUtils.java index 301dc827..756dbbbe 100644 --- a/simplTests/test/legacy/tests/TestingUtils.java +++ b/simplTests/test/legacy/tests/TestingUtils.java @@ -1,78 +1,78 @@ -package legacy.tests; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.deserializers.parsers.tlv.Utils; -import ecologylab.serialization.formatenums.Format; - -public class TestingUtils -{ - - public static void testSerailization(Object object, DualBufferOutputStream outStream, Format format) - throws SIMPLTranslationException - { - SimplTypesScope.serialize(object, outStream, format); - printOutput(outStream, format); - } - - public static void testDeserailization(InputStream inputStream, - SimplTypesScope translationScope, Format format) throws SIMPLTranslationException - { - Object object = translationScope.deserialize(inputStream, format); - DualBufferOutputStream outputStream = new DualBufferOutputStream(); - testSerailization(object, outputStream, Format.XML); - } - - public static void test(Object object, SimplTypesScope translationScope, Format format) - throws SIMPLTranslationException - { - DualBufferOutputStream outputStream = new DualBufferOutputStream(); - - testSerailization(object, outputStream, format); - - testDeserailization(new ByteArrayInputStream(outputStream.toByte()), translationScope, - format); - - System.out.println(); - } - - - public static void serializeSimplTypesScope(SimplTypesScope scope, String fileName, Format format) throws SIMPLTranslationException - { - DualBufferOutputStream outputStream = new DualBufferOutputStream(); - SimplTypesScope.serialize(scope, outputStream, format); - - if (format == Format.JSON) - fileName += ".json"; - else - fileName += ".xml"; - try - { - FileWriter fstream = new FileWriter(fileName); - fstream.write(outputStream.toString()); - fstream.close(); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - - public static void printOutput(DualBufferOutputStream outputStream, Format format) - { - if(format == Format.TLV) - { - Utils.writeHex(System.out, outputStream.toByte()); - } - else - { - System.out.println(outputStream.toString()); - } - } -} +package legacy.tests; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.deserializers.parsers.tlv.Utils; +import ecologylab.serialization.formatenums.Format; + +public class TestingUtils +{ + + public static void testSerailization(Object object, DualBufferOutputStream outStream, Format format) + throws SIMPLTranslationException + { + SimplTypesScope.serialize(object, outStream, format); + printOutput(outStream, format); + } + + public static void testDeserailization(InputStream inputStream, + SimplTypesScope translationScope, Format format) throws SIMPLTranslationException + { + Object object = translationScope.deserialize(inputStream, format); + DualBufferOutputStream outputStream = new DualBufferOutputStream(); + testSerailization(object, outputStream, Format.XML); + } + + public static void test(Object object, SimplTypesScope translationScope, Format format) + throws SIMPLTranslationException + { + DualBufferOutputStream outputStream = new DualBufferOutputStream(); + + testSerailization(object, outputStream, format); + + testDeserailization(new ByteArrayInputStream(outputStream.toByte()), translationScope, + format); + + System.out.println(); + } + + + public static void serializeSimplTypesScope(SimplTypesScope scope, String fileName, Format format) throws SIMPLTranslationException + { + DualBufferOutputStream outputStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(scope, outputStream, format); + + if (format == Format.JSON) + fileName += ".json"; + else + fileName += ".xml"; + try + { + FileWriter fstream = new FileWriter(fileName); + fstream.write(outputStream.toString()); + fstream.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + public static void printOutput(DualBufferOutputStream outputStream, Format format) + { + if(format == Format.TLV) + { + Utils.writeHex(System.out, outputStream.toByte()); + } + else + { + System.out.println(outputStream.toString()); + } + } +} diff --git a/simplTests/test/legacy/tests/circle/Circle.java b/simplTests/test/legacy/tests/circle/Circle.java index dc1d64d4..29bd027c 100644 --- a/simplTests/test/legacy/tests/circle/Circle.java +++ b/simplTests/test/legacy/tests/circle/Circle.java @@ -1,57 +1,58 @@ -package legacy.tests.circle; - -import java.io.File; -import java.io.IOException; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; - -public class Circle implements TestCase -{ - @simpl_hints(Hint.XML_LEAF) - @simpl_scalar - int radius; - - @simpl_composite - Point center; - - public Circle() - { - } - - public Circle(int radius, Point center) - { - this.radius = radius; - this.center = center; - } - - public Circle(int radius, int x, int y) - { - this.radius = radius; - this.center = new Point(x, y); - } - - @Override - public void runTest() throws SIMPLTranslationException - { - Circle c = new Circle(3, 2, 1); - - - SimplTypesScope t = SimplTypesScope.get("circleTScope", Circle.class, Point.class); - - SimplTypesScope.enableGraphSerialization(); - - TestingUtils.test(c, SimplTypesScope.get("circle", Circle.class, Point.class), Format.XML); - - TestingUtils.test(c, SimplTypesScope.get("circle", Circle.class, Point.class), Format.JSON); - TestingUtils.test(c, SimplTypesScope.get("circle", Circle.class, Point.class), Format.TLV); - } -} +package legacy.tests.circle; + +import java.io.File; +import java.io.IOException; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +public class Circle implements TestCase +{ + @simpl_hints(Hint.XML_LEAF) + @simpl_scalar + int radius; + + @simpl_composite + Point center; + + public Circle() + { + } + + public Circle(int radius, Point center) + { + this.radius = radius; + this.center = center; + } + + public Circle(int radius, int x, int y) + { + this.radius = radius; + this.center = new Point(x, y); + } + + @Override + public void runTest() throws SIMPLTranslationException + { + Circle c = new Circle(3, 2, 1); + + + SimplTypesScope t = SimplTypesScope.get("circleTScope", Circle.class, Point.class); + + SimplTypesScope.enableGraphSerialization(); + + TestingUtils.test(c, SimplTypesScope.get("circle", Circle.class, Point.class), Format.XML); + + TestingUtils.test(c, SimplTypesScope.get("circle", Circle.class, Point.class), Format.JSON); + TestingUtils.test(c, SimplTypesScope.get("circle", Circle.class, Point.class), Format.TLV); + } + +} diff --git a/simplTests/test/legacy/tests/circle/CollectionOfCircles.java b/simplTests/test/legacy/tests/circle/CollectionOfCircles.java index eb7b6697..4150aa87 100644 --- a/simplTests/test/legacy/tests/circle/CollectionOfCircles.java +++ b/simplTests/test/legacy/tests/circle/CollectionOfCircles.java @@ -1,59 +1,60 @@ -package legacy.tests.circle; - -import java.util.ArrayList; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; - -public class CollectionOfCircles implements TestCase -{ -// @simpl_nowrap - @simpl_collection("circles") - private ArrayList collectionOfCircles; - - @simpl_hints(Hint.XML_LEAF) - @simpl_scalar - int yo = 1; - - public CollectionOfCircles() - { - collectionOfCircles = new ArrayList(); - } - - public void addCircle(int r, int x, int y) - { - collectionOfCircles.add(new Circle(r, x, y)); - } - - @Override - public void runTest() throws SIMPLTranslationException - { - CollectionOfCircles coc = new CollectionOfCircles(); - - coc.addCircle(1, 2, 3); - coc.addCircle(1, 2, 4); - coc.addCircle(1, 2, 5); - coc.addCircle(1, 2, 6); - coc.addCircle(1, 2, 7); - - SimplTypesScope circleTranslationScope = SimplTypesScope.get("collectionOfCirclesTScope", - CollectionOfCircles.class, Circle.class, Point.class); - - -// TestingUtils.generateCocoaClasses(circleTranslationScope); - - TestingUtils.test(coc, circleTranslationScope, Format.XML); - - TestingUtils.test(coc, circleTranslationScope, Format.JSON); - TestingUtils.test(coc, circleTranslationScope, Format.TLV); - } -} +package legacy.tests.circle; + +import java.util.ArrayList; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +public class CollectionOfCircles implements TestCase +{ +// @simpl_nowrap + @simpl_collection("circles") + private ArrayList collectionOfCircles; + + @simpl_hints(Hint.XML_LEAF) + @simpl_scalar + int yo = 1; + + public CollectionOfCircles() + { + collectionOfCircles = new ArrayList(); + } + + public void addCircle(int r, int x, int y) + { + collectionOfCircles.add(new Circle(r, x, y)); + } + + @Override + public void runTest() throws SIMPLTranslationException + { + CollectionOfCircles coc = new CollectionOfCircles(); + + coc.addCircle(1, 2, 3); + coc.addCircle(1, 2, 4); + coc.addCircle(1, 2, 5); + coc.addCircle(1, 2, 6); + coc.addCircle(1, 2, 7); + + SimplTypesScope circleTranslationScope = SimplTypesScope.get("collectionOfCirclesTScope", + CollectionOfCircles.class, Circle.class, Point.class); + + +// TestingUtils.generateCocoaClasses(circleTranslationScope); + + TestingUtils.test(coc, circleTranslationScope, Format.XML); + + TestingUtils.test(coc, circleTranslationScope, Format.JSON); + TestingUtils.test(coc, circleTranslationScope, Format.TLV); + } + +} diff --git a/simplTests/test/legacy/tests/circle/Point.java b/simplTests/test/legacy/tests/circle/Point.java index bd4d5d2c..11523fb1 100644 --- a/simplTests/test/legacy/tests/circle/Point.java +++ b/simplTests/test/legacy/tests/circle/Point.java @@ -1,65 +1,65 @@ -package legacy.tests.circle; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; - -public class Point implements TestCase -{ - - @simpl_scalar - private int x; - - @simpl_scalar - private int y; - - public Point() - { - - } - - public Point(int x, int y) - { - this.setX(x); - this.setY(y); - } - - public void setX(int x) - { - this.x = x; - } - - public int getX() - { - return x; - } - - public void setY(int y) - { - this.y = y; - } - - public int getY() - { - return y; - } - - @Override - public void runTest() throws SIMPLTranslationException - { - Point p = new Point(1, 2); - SimplTypesScope scope = SimplTypesScope.get("pointTScope", Point.class); - -// TestingUtils.generateCocoaClasses(scope); - - SimplTypesScope.enableGraphSerialization(); - TestingUtils.serializeSimplTypesScope(scope, "Point", Format.JSON); - - TestingUtils.test(p, scope, Format.XML); - TestingUtils.test(p, scope, Format.JSON); - TestingUtils.test(p, scope, Format.TLV); - } -} +package legacy.tests.circle; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +public class Point implements TestCase +{ + + @simpl_scalar + private int x; + + @simpl_scalar + private int y; + + public Point() + { + + } + + public Point(int x, int y) + { + this.setX(x); + this.setY(y); + } + + public void setX(int x) + { + this.x = x; + } + + public int getX() + { + return x; + } + + public void setY(int y) + { + this.y = y; + } + + public int getY() + { + return y; + } + + @Override + public void runTest() throws SIMPLTranslationException + { + Point p = new Point(1, 2); + SimplTypesScope scope = SimplTypesScope.get("pointTScope", Point.class); + +// TestingUtils.generateCocoaClasses(scope); + + SimplTypesScope.enableGraphSerialization(); + TestingUtils.serializeSimplTypesScope(scope, "Point", Format.JSON); + + TestingUtils.test(p, scope, Format.XML); + TestingUtils.test(p, scope, Format.JSON); + TestingUtils.test(p, scope, Format.TLV); + } +} diff --git a/simplTests/test/legacy/tests/circle/circleTypeScope.xml b/simplTests/test/legacy/tests/circle/circleTypeScope.xml index 1ede42c8..e4db239d 100644 --- a/simplTests/test/legacy/tests/circle/circleTypeScope.xml +++ b/simplTests/test/legacy/tests/circle/circleTypeScope.xml @@ -1,30 +1,30 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/simplTests/test/legacy/tests/composite/Container.java b/simplTests/test/legacy/tests/composite/Container.java index 0cf0bc97..fe5c4b6a 100644 --- a/simplTests/test/legacy/tests/composite/Container.java +++ b/simplTests/test/legacy/tests/composite/Container.java @@ -1,40 +1,40 @@ -package legacy.tests.composite; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_classes; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.formatenums.Format; - -public class Container implements TestCase -{ - - // @simpl_wrap - @simpl_composite - @simpl_classes( - { WCBase.class, WCSubOne.class, WCSubTwo.class }) - WCBase wc; - - public Container() - { - wc = new WCBase(0); - } - - @Override - public void runTest() throws SIMPLTranslationException - { - Container c = new Container(); - - c.wc = new WCSubTwo(true); - - SimplTypesScope containerTest = SimplTypesScope.get("containerTranslationscope", - Container.class, WCBase.class, WCSubOne.class, WCSubTwo.class); - - - TestingUtils.test(c, containerTest, Format.XML); - TestingUtils.test(c, containerTest, Format.JSON); - - } -} +package legacy.tests.composite; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_classes; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.formatenums.Format; + +public class Container implements TestCase +{ + + // @simpl_wrap + @simpl_composite + @simpl_classes( + { WCBase.class, WCSubOne.class, WCSubTwo.class }) + WCBase wc; + + public Container() + { + wc = new WCBase(0); + } + + @Override + public void runTest() throws SIMPLTranslationException + { + Container c = new Container(); + + c.wc = new WCSubTwo(true); + + SimplTypesScope containerTest = SimplTypesScope.get("containerTranslationscope", + Container.class, WCBase.class, WCSubOne.class, WCSubTwo.class); + + + TestingUtils.test(c, containerTest, Format.XML); + TestingUtils.test(c, containerTest, Format.JSON); + + } +} diff --git a/simplTests/test/legacy/tests/composite/WCBase.java b/simplTests/test/legacy/tests/composite/WCBase.java index d4f4e003..d4aa4d09 100644 --- a/simplTests/test/legacy/tests/composite/WCBase.java +++ b/simplTests/test/legacy/tests/composite/WCBase.java @@ -1,22 +1,22 @@ -package legacy.tests.composite; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -public class WCBase extends ElementState -{ - - @simpl_scalar - int x; - - public WCBase() - { - x = 0; - } - - public WCBase(int x) - { - this.x = x; - } - -} +package legacy.tests.composite; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +public class WCBase extends ElementState +{ + + @simpl_scalar + int x; + + public WCBase() + { + x = 0; + } + + public WCBase(int x) + { + this.x = x; + } + +} diff --git a/simplTests/test/legacy/tests/composite/WCSubOne.java b/simplTests/test/legacy/tests/composite/WCSubOne.java index 934137dd..f59f4c17 100644 --- a/simplTests/test/legacy/tests/composite/WCSubOne.java +++ b/simplTests/test/legacy/tests/composite/WCSubOne.java @@ -1,22 +1,22 @@ -package legacy.tests.composite; - -import ecologylab.serialization.annotations.simpl_scalar; - - -public class WCSubOne extends WCBase -{ - - @simpl_scalar - String subString; - - public WCSubOne() - { - subString = ""; - } - - public WCSubOne(String subString) - { - this.subString = subString; - this.x = 4; - } -} +package legacy.tests.composite; + +import ecologylab.serialization.annotations.simpl_scalar; + + +public class WCSubOne extends WCBase +{ + + @simpl_scalar + String subString; + + public WCSubOne() + { + subString = ""; + } + + public WCSubOne(String subString) + { + this.subString = subString; + this.x = 4; + } +} diff --git a/simplTests/test/legacy/tests/composite/WCSubTwo.java b/simplTests/test/legacy/tests/composite/WCSubTwo.java index 86314987..6c5dbc73 100644 --- a/simplTests/test/legacy/tests/composite/WCSubTwo.java +++ b/simplTests/test/legacy/tests/composite/WCSubTwo.java @@ -1,21 +1,21 @@ -package legacy.tests.composite; - -import ecologylab.serialization.annotations.simpl_scalar; - -public class WCSubTwo extends WCBase -{ - - @simpl_scalar - Boolean myBool; - - public WCSubTwo() - { - myBool = false; - } - - public WCSubTwo(Boolean myBool) - { - this.myBool = myBool; - this.x = 5; - } +package legacy.tests.composite; + +import ecologylab.serialization.annotations.simpl_scalar; + +public class WCSubTwo extends WCBase +{ + + @simpl_scalar + Boolean myBool; + + public WCSubTwo() + { + myBool = false; + } + + public WCSubTwo(Boolean myBool) + { + this.myBool = myBool; + this.x = 5; + } } \ No newline at end of file diff --git a/simplTests/test/legacy/tests/configuration/Configuration.java b/simplTests/test/legacy/tests/configuration/Configuration.java index 76e10699..ac2bac85 100644 --- a/simplTests/test/legacy/tests/configuration/Configuration.java +++ b/simplTests/test/legacy/tests/configuration/Configuration.java @@ -1,64 +1,64 @@ -package legacy.tests.configuration; - -import java.util.ArrayList; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_classes; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.formatenums.Format; - -public class Configuration implements TestCase -{ - @simpl_classes( - { Pref.class, PrefDouble.class, PrefInteger.class }) - @simpl_composite - public Pref pref; - - @simpl_classes( - { Pref.class, PrefDouble.class, PrefInteger.class }) - @simpl_collection - public ArrayList prefs; - - public Configuration() - { - - } - - @Override - public void runTest() throws SIMPLTranslationException - { - SimplTypesScope translationScope = SimplTypesScope.get("configurationTScope", Configuration.class, Pref.class, - PrefInteger.class, PrefDouble.class, Pref.class); - - Configuration configuration = new Configuration(); - - PrefInteger prefInteger = new PrefInteger(); - prefInteger.name = "integer_pref"; - prefInteger.intValue = 2; - - PrefDouble prefDouble = new PrefDouble(); - prefDouble.name = "double_pref"; - prefDouble.doubleValue = 5; - - Pref pref = new Pref(); - pref.name = "only_pref"; - - ArrayList prefList = new ArrayList(); - prefList.add(pref); - prefList.add(prefInteger); - prefList.add(prefDouble); - - configuration.pref = prefInteger; - configuration.prefs = prefList; - - TestingUtils.test(configuration, translationScope, Format.XML); - TestingUtils.test(configuration, translationScope, Format.JSON); - TestingUtils.test(configuration, translationScope, Format.TLV); - - } -} +package legacy.tests.configuration; + +import java.util.ArrayList; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_classes; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.formatenums.Format; + +public class Configuration implements TestCase +{ + @simpl_classes( + { Pref.class, PrefDouble.class, PrefInteger.class }) + @simpl_composite + public Pref pref; + + @simpl_classes( + { Pref.class, PrefDouble.class, PrefInteger.class }) + @simpl_collection + public ArrayList prefs; + + public Configuration() + { + + } + + @Override + public void runTest() throws SIMPLTranslationException + { + SimplTypesScope translationScope = SimplTypesScope.get("configurationTScope", Configuration.class, Pref.class, + PrefInteger.class, PrefDouble.class, Pref.class); + + Configuration configuration = new Configuration(); + + PrefInteger prefInteger = new PrefInteger(); + prefInteger.name = "integer_pref"; + prefInteger.intValue = 2; + + PrefDouble prefDouble = new PrefDouble(); + prefDouble.name = "double_pref"; + prefDouble.doubleValue = 5; + + Pref pref = new Pref(); + pref.name = "only_pref"; + + ArrayList prefList = new ArrayList(); + prefList.add(pref); + prefList.add(prefInteger); + prefList.add(prefDouble); + + configuration.pref = prefInteger; + configuration.prefs = prefList; + + TestingUtils.test(configuration, translationScope, Format.XML); + TestingUtils.test(configuration, translationScope, Format.JSON); + TestingUtils.test(configuration, translationScope, Format.TLV); + + } +} diff --git a/simplTests/test/legacy/tests/configuration/Pref.java b/simplTests/test/legacy/tests/configuration/Pref.java index de4f22e2..e84bad6a 100644 --- a/simplTests/test/legacy/tests/configuration/Pref.java +++ b/simplTests/test/legacy/tests/configuration/Pref.java @@ -1,14 +1,14 @@ -package legacy.tests.configuration; - -import ecologylab.serialization.annotations.simpl_scalar; - -public class Pref -{ - @simpl_scalar - public String name; - - public Pref() - { - - } -} +package legacy.tests.configuration; + +import ecologylab.serialization.annotations.simpl_scalar; + +public class Pref +{ + @simpl_scalar + public String name; + + public Pref() + { + + } +} diff --git a/simplTests/test/legacy/tests/configuration/PrefDouble.java b/simplTests/test/legacy/tests/configuration/PrefDouble.java index 528f55e0..d8930321 100644 --- a/simplTests/test/legacy/tests/configuration/PrefDouble.java +++ b/simplTests/test/legacy/tests/configuration/PrefDouble.java @@ -1,16 +1,16 @@ -package legacy.tests.configuration; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -@simpl_inherit -public class PrefDouble extends Pref -{ - @simpl_scalar - public double doubleValue; - - public PrefDouble() - { - - } -} +package legacy.tests.configuration; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +@simpl_inherit +public class PrefDouble extends Pref +{ + @simpl_scalar + public double doubleValue; + + public PrefDouble() + { + + } +} diff --git a/simplTests/test/legacy/tests/configuration/PrefInteger.java b/simplTests/test/legacy/tests/configuration/PrefInteger.java index d99bd051..d3f73804 100644 --- a/simplTests/test/legacy/tests/configuration/PrefInteger.java +++ b/simplTests/test/legacy/tests/configuration/PrefInteger.java @@ -1,16 +1,16 @@ -package legacy.tests.configuration; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -@simpl_inherit -public class PrefInteger extends Pref -{ - @simpl_scalar - public int intValue; - - public PrefInteger() - { - - } -} +package legacy.tests.configuration; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +@simpl_inherit +public class PrefInteger extends Pref +{ + @simpl_scalar + public int intValue; + + public PrefInteger() + { + + } +} diff --git a/simplTests/test/legacy/tests/deserialization/JSONPullDeserializerTest.java b/simplTests/test/legacy/tests/deserialization/JSONPullDeserializerTest.java index ee6d3cf9..576ffe43 100644 --- a/simplTests/test/legacy/tests/deserialization/JSONPullDeserializerTest.java +++ b/simplTests/test/legacy/tests/deserialization/JSONPullDeserializerTest.java @@ -1,201 +1,201 @@ -package legacy.tests.deserialization; - -import java.util.ArrayList; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import ecologylab.generic.HashMapArrayList; -import ecologylab.serialization.JSONTools; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_map; -import ecologylab.serialization.annotations.simpl_map_key_field; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.StringFormat; -import ecologylab.serialization.types.element.IMappable; - -/** - * Test cases for some edge behaviors of the JSON pull deserializer. - * - * @author quyin - * - */ -public class JSONPullDeserializerTest extends Assert -{ - - public static class Item implements IMappable - { - - @simpl_scalar - String name; - - @simpl_scalar - String payload; - - @simpl_map("assoc_item") - HashMapArrayList assocItems; - - @simpl_collection("alias") - ArrayList aliases = new ArrayList(); - - public Item() - { - } - - public Item(String name, String payload) - { - this.name = name; - this.payload = payload; - } - - @Override - public String key() - { - return name; - } - - /** - * (If call with null, create an empty collection). - * - * @param assocItem - */ - public void addAssocItem(Item assocItem) - { - if (assocItems == null) - assocItems = new HashMapArrayList(); - if (assocItem != null) - assocItems.put(assocItem.key(), assocItem); - } - - /** - * (If call with null, create an empty collection). - * - * @param alias - */ - public void addAlias(String alias) - { - if (aliases == null) - aliases = new ArrayList(); - if (alias != null) - aliases.add(alias); - } - - } - - public static class ItemSet - { - - @simpl_scalar - String setName; - - @simpl_nowrap - @simpl_map("item") - @simpl_map_key_field("name") - HashMapArrayList items; - - public void addItem(Item item) - { - if (items == null) - items = new HashMapArrayList(); - items.put(item.key(), item); - } - } - - static SimplTypesScope tscope; - - static - { - tscope = SimplTypesScope.get("test-json-pull-deserializer", - Item.class, - ItemSet.class); - } - - Item item1; - - Item item2; - - ItemSet itemSet; - - @Before - public void prepare() - { - item1 = new Item("item1", "an awesome item"); - item2 = new Item("item2", "an even more awesome item!"); - itemSet = new ItemSet(); - itemSet.addItem(item1); - itemSet.addItem(item2); - } - - void serializeAndValidate() throws SIMPLTranslationException - { - String json = SimplTypesScope.serialize(itemSet, StringFormat.JSON).toString(); - System.out.println("serialized json string:\n" + json); - assertTrue(JSONTools.validate(json)); - - ItemSet newItemSet = (ItemSet) tscope.deserialize(json, StringFormat.JSON); - assertNotNull(newItemSet); - assertNotNull(newItemSet.items); - assertEquals(2, newItemSet.items.size()); - assertEquals("item1", newItemSet.items.get(0).key()); - assertEquals("item2", newItemSet.items.get(1).key()); - } - - /** - * Basic de/serialization. - * - * @throws SIMPLTranslationException - */ - @Test - public void deSerializeItems() throws SIMPLTranslationException - { - serializeAndValidate(); - } - - /** - * In a collection of objects (such as ItemSet.items), test if an empty map in the end of the - * serialization of an object will cause problem for parsing the next object. - * - * @throws SIMPLTranslationException - */ - @Test(timeout = 2000) - public void deSerializeEmptyMapInCollectionJSON() throws SIMPLTranslationException - { - item1.addAssocItem(null); - - serializeAndValidate(); - } - - @Test(timeout=2000) - public void deSerializeNonEmptyMapInCollectionJSON() throws SIMPLTranslationException - { - item1.addAssocItem(item2); - - serializeAndValidate(); - } - - /** - * A collection of scalars can also mess up following tokens. - * - * @throws SIMPLTranslationException - */ - @Test(timeout=2000) - public void deSerializeEmptyCollectionOfScalarsJSON() throws SIMPLTranslationException - { - item1.addAlias(null); - - serializeAndValidate(); - } - - @Test(timeout=2000) - public void deSerializeNonEmptyCollectionOfScalarsJSON() throws SIMPLTranslationException - { - item1.addAlias("item one"); - - serializeAndValidate(); - } - -} +package legacy.tests.deserialization; + +import java.util.ArrayList; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import ecologylab.generic.HashMapArrayList; +import ecologylab.serialization.JSONTools; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_map; +import ecologylab.serialization.annotations.simpl_map_key_field; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.StringFormat; +import ecologylab.serialization.types.element.IMappable; + +/** + * Test cases for some edge behaviors of the JSON pull deserializer. + * + * @author quyin + * + */ +public class JSONPullDeserializerTest extends Assert +{ + + public static class Item implements IMappable + { + + @simpl_scalar + String name; + + @simpl_scalar + String payload; + + @simpl_map("assoc_item") + HashMapArrayList assocItems; + + @simpl_collection("alias") + ArrayList aliases = new ArrayList(); + + public Item() + { + } + + public Item(String name, String payload) + { + this.name = name; + this.payload = payload; + } + + @Override + public String key() + { + return name; + } + + /** + * (If call with null, create an empty collection). + * + * @param assocItem + */ + public void addAssocItem(Item assocItem) + { + if (assocItems == null) + assocItems = new HashMapArrayList(); + if (assocItem != null) + assocItems.put(assocItem.key(), assocItem); + } + + /** + * (If call with null, create an empty collection). + * + * @param alias + */ + public void addAlias(String alias) + { + if (aliases == null) + aliases = new ArrayList(); + if (alias != null) + aliases.add(alias); + } + + } + + public static class ItemSet + { + + @simpl_scalar + String setName; + + @simpl_nowrap + @simpl_map("item") + @simpl_map_key_field("name") + HashMapArrayList items; + + public void addItem(Item item) + { + if (items == null) + items = new HashMapArrayList(); + items.put(item.key(), item); + } + } + + static SimplTypesScope tscope; + + static + { + tscope = SimplTypesScope.get("test-json-pull-deserializer", + Item.class, + ItemSet.class); + } + + Item item1; + + Item item2; + + ItemSet itemSet; + + @Before + public void prepare() + { + item1 = new Item("item1", "an awesome item"); + item2 = new Item("item2", "an even more awesome item!"); + itemSet = new ItemSet(); + itemSet.addItem(item1); + itemSet.addItem(item2); + } + + void serializeAndValidate() throws SIMPLTranslationException + { + String json = SimplTypesScope.serialize(itemSet, StringFormat.JSON).toString(); + System.out.println("serialized json string:\n" + json); + assertTrue(JSONTools.validate(json)); + + ItemSet newItemSet = (ItemSet) tscope.deserialize(json, StringFormat.JSON); + assertNotNull(newItemSet); + assertNotNull(newItemSet.items); + assertEquals(2, newItemSet.items.size()); + assertEquals("item1", newItemSet.items.get(0).key()); + assertEquals("item2", newItemSet.items.get(1).key()); + } + + /** + * Basic de/serialization. + * + * @throws SIMPLTranslationException + */ + @Test + public void deSerializeItems() throws SIMPLTranslationException + { + serializeAndValidate(); + } + + /** + * In a collection of objects (such as ItemSet.items), test if an empty map in the end of the + * serialization of an object will cause problem for parsing the next object. + * + * @throws SIMPLTranslationException + */ + @Test(timeout = 2000) + public void deSerializeEmptyMapInCollectionJSON() throws SIMPLTranslationException + { + item1.addAssocItem(null); + + serializeAndValidate(); + } + + @Test(timeout=2000) + public void deSerializeNonEmptyMapInCollectionJSON() throws SIMPLTranslationException + { + item1.addAssocItem(item2); + + serializeAndValidate(); + } + + /** + * A collection of scalars can also mess up following tokens. + * + * @throws SIMPLTranslationException + */ + @Test(timeout=2000) + public void deSerializeEmptyCollectionOfScalarsJSON() throws SIMPLTranslationException + { + item1.addAlias(null); + + serializeAndValidate(); + } + + @Test(timeout=2000) + public void deSerializeNonEmptyCollectionOfScalarsJSON() throws SIMPLTranslationException + { + item1.addAlias("item one"); + + serializeAndValidate(); + } + +} diff --git a/simplTests/test/legacy/tests/generics/FlickrSearchResult.java b/simplTests/test/legacy/tests/generics/FlickrSearchResult.java index 1047b215..9f163a34 100644 --- a/simplTests/test/legacy/tests/generics/FlickrSearchResult.java +++ b/simplTests/test/legacy/tests/generics/FlickrSearchResult.java @@ -1,9 +1,9 @@ -package legacy.tests.generics; - -import ecologylab.serialization.annotations.simpl_inherit; - -@simpl_inherit -public class FlickrSearchResult extends MediaSearchResult -{ - -} +package legacy.tests.generics; + +import ecologylab.serialization.annotations.simpl_inherit; + +@simpl_inherit +public class FlickrSearchResult extends MediaSearchResult +{ + +} diff --git a/simplTests/test/legacy/tests/generics/Image.java b/simplTests/test/legacy/tests/generics/Image.java index 09952d0c..77798bc0 100644 --- a/simplTests/test/legacy/tests/generics/Image.java +++ b/simplTests/test/legacy/tests/generics/Image.java @@ -1,16 +1,16 @@ -package legacy.tests.generics; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -@simpl_inherit -public class Image extends Media -{ - - @simpl_scalar - int width; - - @simpl_scalar - int height; - -} +package legacy.tests.generics; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +@simpl_inherit +public class Image extends Media +{ + + @simpl_scalar + int width; + + @simpl_scalar + int height; + +} diff --git a/simplTests/test/legacy/tests/generics/ImageSearch.java b/simplTests/test/legacy/tests/generics/ImageSearch.java index 721651a9..8c98042d 100644 --- a/simplTests/test/legacy/tests/generics/ImageSearch.java +++ b/simplTests/test/legacy/tests/generics/ImageSearch.java @@ -1,9 +1,9 @@ -package legacy.tests.generics; - -import ecologylab.serialization.annotations.simpl_inherit; - -@simpl_inherit -public class ImageSearch> extends MediaSearch -{ - -} +package legacy.tests.generics; + +import ecologylab.serialization.annotations.simpl_inherit; + +@simpl_inherit +public class ImageSearch> extends MediaSearch +{ + +} diff --git a/simplTests/test/legacy/tests/generics/Media.java b/simplTests/test/legacy/tests/generics/Media.java index eea337d9..33a53a23 100644 --- a/simplTests/test/legacy/tests/generics/Media.java +++ b/simplTests/test/legacy/tests/generics/Media.java @@ -1,11 +1,11 @@ -package legacy.tests.generics; - -import ecologylab.serialization.annotations.simpl_scalar; - -public class Media -{ - - @simpl_scalar - String data; // base64 encoded - -} +package legacy.tests.generics; + +import ecologylab.serialization.annotations.simpl_scalar; + +public class Media +{ + + @simpl_scalar + String data; // base64 encoded + +} diff --git a/simplTests/test/legacy/tests/generics/MediaSearch.java b/simplTests/test/legacy/tests/generics/MediaSearch.java index e8a02ee2..e66f2e9f 100644 --- a/simplTests/test/legacy/tests/generics/MediaSearch.java +++ b/simplTests/test/legacy/tests/generics/MediaSearch.java @@ -1,13 +1,13 @@ -package legacy.tests.generics; - -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_inherit; - -@simpl_inherit -public class MediaSearch> extends Search -{ - - @simpl_composite - MediaSearchResult firstResult; - -} +package legacy.tests.generics; + +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_inherit; + +@simpl_inherit +public class MediaSearch> extends Search +{ + + @simpl_composite + MediaSearchResult firstResult; + +} diff --git a/simplTests/test/legacy/tests/generics/Search.java b/simplTests/test/legacy/tests/generics/Search.java index 5f2b5c2d..eca610db 100644 --- a/simplTests/test/legacy/tests/generics/Search.java +++ b/simplTests/test/legacy/tests/generics/Search.java @@ -1,13 +1,13 @@ -package legacy.tests.generics; - -import java.util.List; - -import ecologylab.serialization.annotations.simpl_collection; - -public class Search -{ - - @simpl_collection("result") - List results; - -} +package legacy.tests.generics; + +import java.util.List; + +import ecologylab.serialization.annotations.simpl_collection; + +public class Search +{ + + @simpl_collection("result") + List results; + +} diff --git a/simplTests/test/legacy/tests/generics/SearchResult.java b/simplTests/test/legacy/tests/generics/SearchResult.java index 6d760284..95513307 100644 --- a/simplTests/test/legacy/tests/generics/SearchResult.java +++ b/simplTests/test/legacy/tests/generics/SearchResult.java @@ -1,11 +1,11 @@ -package legacy.tests.generics; - -import ecologylab.serialization.annotations.simpl_scalar; - -public class SearchResult -{ - - @simpl_scalar - String title; - -} +package legacy.tests.generics; + +import ecologylab.serialization.annotations.simpl_scalar; + +public class SearchResult +{ + + @simpl_scalar + String title; + +} diff --git a/simplTests/test/legacy/tests/graph/ClassA.java b/simplTests/test/legacy/tests/graph/ClassA.java index 5917105d..ee3539d2 100644 --- a/simplTests/test/legacy/tests/graph/ClassA.java +++ b/simplTests/test/legacy/tests/graph/ClassA.java @@ -1,107 +1,107 @@ -package legacy.tests.graph; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; - -@simpl_inherit -public class ClassA implements TestCase -{ - @simpl_scalar - private int x; - - @simpl_scalar - private int y; - - @simpl_composite - private ClassB classB; - - @simpl_composite - private ClassA classA; - - public ClassA() - { - - } - - public ClassA(int x, int y) - { - setX(x); - setY(y); - setClassA(this); - } - - public ClassA(int x, int y, ClassB classB) - { - setX(x); - setY(y); - setClassB(classB); - setClassA(this); - } - - public void setX(int x) - { - this.x = x; - } - - public int getX() - { - return x; - } - - public void setY(int y) - { - this.y = y; - } - - public int getY() - { - return y; - } - - public void setClassB(ClassB classB) - { - this.classB = classB; - } - - public ClassB getClassB() - { - return classB; - } - - public void setClassA(ClassA classA) - { - this.classA = classA; - } - - public ClassA getClassA() - { - return classA; - } - - @Override - public void runTest() throws SIMPLTranslationException - { - SimplTypesScope.enableGraphSerialization(); - - ClassA test = new ClassA(1, 2); - ClassB classB = new ClassB(3, 4, test); - - test.setClassB(classB); - - SimplTypesScope tScope = SimplTypesScope.get("classATScope", ClassA.class, ClassB.class); - -// TestingUtils.generateCocoaClasses(tScope); - - TestingUtils.test(test, tScope, Format.XML); - TestingUtils.test(test, tScope, Format.JSON); - TestingUtils.test(test, tScope, Format.TLV); - - SimplTypesScope.disableGraphSerialization(); - } -} +package legacy.tests.graph; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +@simpl_inherit +public class ClassA implements TestCase +{ + @simpl_scalar + private int x; + + @simpl_scalar + private int y; + + @simpl_composite + private ClassB classB; + + @simpl_composite + private ClassA classA; + + public ClassA() + { + + } + + public ClassA(int x, int y) + { + setX(x); + setY(y); + setClassA(this); + } + + public ClassA(int x, int y, ClassB classB) + { + setX(x); + setY(y); + setClassB(classB); + setClassA(this); + } + + public void setX(int x) + { + this.x = x; + } + + public int getX() + { + return x; + } + + public void setY(int y) + { + this.y = y; + } + + public int getY() + { + return y; + } + + public void setClassB(ClassB classB) + { + this.classB = classB; + } + + public ClassB getClassB() + { + return classB; + } + + public void setClassA(ClassA classA) + { + this.classA = classA; + } + + public ClassA getClassA() + { + return classA; + } + + @Override + public void runTest() throws SIMPLTranslationException + { + SimplTypesScope.enableGraphSerialization(); + + ClassA test = new ClassA(1, 2); + ClassB classB = new ClassB(3, 4, test); + + test.setClassB(classB); + + SimplTypesScope tScope = SimplTypesScope.get("classATScope", ClassA.class, ClassB.class); + +// TestingUtils.generateCocoaClasses(tScope); + + TestingUtils.test(test, tScope, Format.XML); + TestingUtils.test(test, tScope, Format.JSON); + TestingUtils.test(test, tScope, Format.TLV); + + SimplTypesScope.disableGraphSerialization(); + } +} diff --git a/simplTests/test/legacy/tests/graph/ClassB.java b/simplTests/test/legacy/tests/graph/ClassB.java index 0005066a..50a228b6 100644 --- a/simplTests/test/legacy/tests/graph/ClassB.java +++ b/simplTests/test/legacy/tests/graph/ClassB.java @@ -1,88 +1,88 @@ -package legacy.tests.graph; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; - -public class ClassB implements TestCase -{ - @simpl_scalar - private int a; - - @simpl_scalar - private int b; - - @simpl_composite - private ClassA classA; - - public ClassB() - { - - } - - public ClassB(int a, int b) - { - this.a = a; - this.b = b; - } - - public ClassB(int a, int b, ClassA classA) - { - this.a = a; - this.b = b; - this.classA = classA; - } - - public void setClassA(ClassA classA) - { - this.classA = classA; - } - - public ClassA getClassA() - { - return classA; - } - - public void setB(int b) - { - this.b = b; - } - - public int getB() - { - return b; - } - - public void setA(int a) - { - this.a = a; - } - - public int getA() - { - return a; - } - - @Override - public void runTest() throws SIMPLTranslationException - { - SimplTypesScope.enableGraphSerialization(); - - ClassB test = new ClassB(1, 2); - ClassA classA = new ClassA(3, 4, test); - - test.setClassA(classA); - - SimplTypesScope tScope = SimplTypesScope.get("classB", ClassA.class, ClassB.class); - - TestingUtils.test(test, tScope, Format.XML); - TestingUtils.test(test, tScope, Format.JSON); - TestingUtils.test(test, tScope, Format.TLV); - - SimplTypesScope.disableGraphSerialization(); - } -} +package legacy.tests.graph; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +public class ClassB implements TestCase +{ + @simpl_scalar + private int a; + + @simpl_scalar + private int b; + + @simpl_composite + private ClassA classA; + + public ClassB() + { + + } + + public ClassB(int a, int b) + { + this.a = a; + this.b = b; + } + + public ClassB(int a, int b, ClassA classA) + { + this.a = a; + this.b = b; + this.classA = classA; + } + + public void setClassA(ClassA classA) + { + this.classA = classA; + } + + public ClassA getClassA() + { + return classA; + } + + public void setB(int b) + { + this.b = b; + } + + public int getB() + { + return b; + } + + public void setA(int a) + { + this.a = a; + } + + public int getA() + { + return a; + } + + @Override + public void runTest() throws SIMPLTranslationException + { + SimplTypesScope.enableGraphSerialization(); + + ClassB test = new ClassB(1, 2); + ClassA classA = new ClassA(3, 4, test); + + test.setClassA(classA); + + SimplTypesScope tScope = SimplTypesScope.get("classB", ClassA.class, ClassB.class); + + TestingUtils.test(test, tScope, Format.XML); + TestingUtils.test(test, tScope, Format.JSON); + TestingUtils.test(test, tScope, Format.TLV); + + SimplTypesScope.disableGraphSerialization(); + } +} diff --git a/simplTests/test/legacy/tests/graph/collections/ClassA.java b/simplTests/test/legacy/tests/graph/collections/ClassA.java index d8119bf9..51c1bdfa 100644 --- a/simplTests/test/legacy/tests/graph/collections/ClassA.java +++ b/simplTests/test/legacy/tests/graph/collections/ClassA.java @@ -1,39 +1,39 @@ -package legacy.tests.graph.collections; - -import ecologylab.serialization.annotations.simpl_scalar; - -public class ClassA -{ - @simpl_scalar - private int u; - - @simpl_scalar - private int w; - - public ClassA() - { - setU(55); - setW(54); - } - - public void setU(int u) - { - this.u = u; - } - - public int getU() - { - return u; - } - - public void setW(int w) - { - this.w = w; - } - - public int getW() - { - return w; - } - -} +package legacy.tests.graph.collections; + +import ecologylab.serialization.annotations.simpl_scalar; + +public class ClassA +{ + @simpl_scalar + private int u; + + @simpl_scalar + private int w; + + public ClassA() + { + setU(55); + setW(54); + } + + public void setU(int u) + { + this.u = u; + } + + public int getU() + { + return u; + } + + public void setW(int w) + { + this.w = w; + } + + public int getW() + { + return w; + } + +} diff --git a/simplTests/test/legacy/tests/graph/collections/ClassB.java b/simplTests/test/legacy/tests/graph/collections/ClassB.java index 2dcfbf5c..f1716bb3 100644 --- a/simplTests/test/legacy/tests/graph/collections/ClassB.java +++ b/simplTests/test/legacy/tests/graph/collections/ClassB.java @@ -1,38 +1,38 @@ -package legacy.tests.graph.collections; - -import ecologylab.serialization.annotations.simpl_scalar; - -public class ClassB -{ - @simpl_scalar - private int u; - - @simpl_scalar - private int w; - - public ClassB() - { - setU(55); - setW(54); - } - - public void setU(int u) - { - this.u = u; - } - - public int getU() - { - return u; - } - - public void setW(int w) - { - this.w = w; - } - - public int getW() - { - return w; - } -} +package legacy.tests.graph.collections; + +import ecologylab.serialization.annotations.simpl_scalar; + +public class ClassB +{ + @simpl_scalar + private int u; + + @simpl_scalar + private int w; + + public ClassB() + { + setU(55); + setW(54); + } + + public void setU(int u) + { + this.u = u; + } + + public int getU() + { + return u; + } + + public void setW(int w) + { + this.w = w; + } + + public int getW() + { + return w; + } +} diff --git a/simplTests/test/legacy/tests/graph/collections/Container.java b/simplTests/test/legacy/tests/graph/collections/Container.java index 6339ca7e..1152a72a 100644 --- a/simplTests/test/legacy/tests/graph/collections/Container.java +++ b/simplTests/test/legacy/tests/graph/collections/Container.java @@ -1,77 +1,77 @@ -package legacy.tests.graph.collections; - -import java.util.ArrayList; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.formatenums.Format; - -public class Container implements TestCase -{ - - @simpl_collection("objectsA") - private ArrayList aObjects = new ArrayList(); - - public Container() - { - - } - - public Container initializeInstance() - { - ClassA objA = new ClassA(); - - aObjects.add(objA); - aObjects.add(objA); - aObjects.add(objA); - aObjects.add(objA); - aObjects.add(objA); - aObjects.add(objA); - aObjects.add(objA); - aObjects.add(objA); - aObjects.add(objA); - aObjects.add(objA); - aObjects.add(objA); - aObjects.add(objA); - aObjects.add(objA); - - aObjects.add(new ClassA()); - aObjects.add(new ClassA()); - - return this; - } - - public void setAobjects(ArrayList aobjects) - { - aObjects = aobjects; - } - - public ArrayList getAobjects() - { - return aObjects; - } - - @Override - public void runTest() throws SIMPLTranslationException - { - SimplTypesScope.enableGraphSerialization(); - - Container test = new Container().initializeInstance(); - SimplTypesScope translationScope = SimplTypesScope.get("containerTScope", Container.class, - ClassA.class); - -// TestingUtils.generateCocoaClasses(translationScope); - - TestingUtils.test(test, translationScope, Format.XML); - TestingUtils.test(test, translationScope, Format.JSON); - TestingUtils.test(test, translationScope, Format.TLV); - - SimplTypesScope.disableGraphSerialization(); - - } - -} +package legacy.tests.graph.collections; + +import java.util.ArrayList; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.formatenums.Format; + +public class Container implements TestCase +{ + + @simpl_collection("objectsA") + private ArrayList aObjects = new ArrayList(); + + public Container() + { + + } + + public Container initializeInstance() + { + ClassA objA = new ClassA(); + + aObjects.add(objA); + aObjects.add(objA); + aObjects.add(objA); + aObjects.add(objA); + aObjects.add(objA); + aObjects.add(objA); + aObjects.add(objA); + aObjects.add(objA); + aObjects.add(objA); + aObjects.add(objA); + aObjects.add(objA); + aObjects.add(objA); + aObjects.add(objA); + + aObjects.add(new ClassA()); + aObjects.add(new ClassA()); + + return this; + } + + public void setAobjects(ArrayList aobjects) + { + aObjects = aobjects; + } + + public ArrayList getAobjects() + { + return aObjects; + } + + @Override + public void runTest() throws SIMPLTranslationException + { + SimplTypesScope.enableGraphSerialization(); + + Container test = new Container().initializeInstance(); + SimplTypesScope translationScope = SimplTypesScope.get("containerTScope", Container.class, + ClassA.class); + +// TestingUtils.generateCocoaClasses(translationScope); + + TestingUtils.test(test, translationScope, Format.XML); + TestingUtils.test(test, translationScope, Format.JSON); + TestingUtils.test(test, translationScope, Format.TLV); + + SimplTypesScope.disableGraphSerialization(); + + } + +} diff --git a/simplTests/test/legacy/tests/graph/diamond/ClassA.java b/simplTests/test/legacy/tests/graph/diamond/ClassA.java index 9c516b1f..ada16781 100644 --- a/simplTests/test/legacy/tests/graph/diamond/ClassA.java +++ b/simplTests/test/legacy/tests/graph/diamond/ClassA.java @@ -1,58 +1,58 @@ -package legacy.tests.graph.diamond; - -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_scalar; - -public class ClassA -{ - @simpl_scalar - private int x; - - @simpl_scalar - private int y; - - @simpl_composite - private ClassC classC; - - public ClassA() - { - - } - - public ClassA(ClassC classC) - { - setX(1); - setY(2); - this.setClassC(classC); - } - - public void setX(int x) - { - this.x = x; - } - - public int getX() - { - return x; - } - - public void setY(int y) - { - this.y = y; - } - - public int getY() - { - return y; - } - - public void setClassC(ClassC classC) - { - this.classC = classC; - } - - public ClassC getClassC() - { - return classC; - } -} +package legacy.tests.graph.diamond; + +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_scalar; + +public class ClassA +{ + @simpl_scalar + private int x; + + @simpl_scalar + private int y; + + @simpl_composite + private ClassC classC; + + public ClassA() + { + + } + + public ClassA(ClassC classC) + { + setX(1); + setY(2); + this.setClassC(classC); + } + + public void setX(int x) + { + this.x = x; + } + + public int getX() + { + return x; + } + + public void setY(int y) + { + this.y = y; + } + + public int getY() + { + return y; + } + + public void setClassC(ClassC classC) + { + this.classC = classC; + } + + public ClassC getClassC() + { + return classC; + } +} diff --git a/simplTests/test/legacy/tests/graph/diamond/ClassB.java b/simplTests/test/legacy/tests/graph/diamond/ClassB.java index fe0fef50..31625b51 100644 --- a/simplTests/test/legacy/tests/graph/diamond/ClassB.java +++ b/simplTests/test/legacy/tests/graph/diamond/ClassB.java @@ -1,71 +1,71 @@ -package legacy.tests.graph.diamond; - -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_scalar; - -public class ClassB -{ - @simpl_scalar - private int x; - - @simpl_scalar - private int y; - - @simpl_composite - private ClassC classC; - - @simpl_composite - private ClassX classX; - - public ClassB() - { - } - - public ClassB(ClassC classC) - { - setX(1); - setY(2); - this.setClassC(classC); - setClassX(new ClassX()); - } - - public void setX(int x) - { - this.x = x; - } - - public int getX() - { - return x; - } - - public void setY(int y) - { - this.y = y; - } - - public int getY() - { - return y; - } - - public void setClassC(ClassC classC) - { - this.classC = classC; - } - - public ClassC getClassC() - { - return classC; - } - - public void setClassX(ClassX classX) - { - this.classX = classX; - } - - public ClassX getClassX() - { - return classX; - } -} +package legacy.tests.graph.diamond; + +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_scalar; + +public class ClassB +{ + @simpl_scalar + private int x; + + @simpl_scalar + private int y; + + @simpl_composite + private ClassC classC; + + @simpl_composite + private ClassX classX; + + public ClassB() + { + } + + public ClassB(ClassC classC) + { + setX(1); + setY(2); + this.setClassC(classC); + setClassX(new ClassX()); + } + + public void setX(int x) + { + this.x = x; + } + + public int getX() + { + return x; + } + + public void setY(int y) + { + this.y = y; + } + + public int getY() + { + return y; + } + + public void setClassC(ClassC classC) + { + this.classC = classC; + } + + public ClassC getClassC() + { + return classC; + } + + public void setClassX(ClassX classX) + { + this.classX = classX; + } + + public ClassX getClassX() + { + return classX; + } +} diff --git a/simplTests/test/legacy/tests/graph/diamond/ClassC.java b/simplTests/test/legacy/tests/graph/diamond/ClassC.java index 9776d9d0..f2d1023d 100644 --- a/simplTests/test/legacy/tests/graph/diamond/ClassC.java +++ b/simplTests/test/legacy/tests/graph/diamond/ClassC.java @@ -1,38 +1,38 @@ -package legacy.tests.graph.diamond; - -import ecologylab.serialization.annotations.simpl_scalar; - -public class ClassC -{ - @simpl_scalar - private int u; - - @simpl_scalar - private int w; - - public ClassC() - { - setU(55); - setW(54); - } - - public void setU(int u) - { - this.u = u; - } - - public int getU() - { - return u; - } - - public void setW(int w) - { - this.w = w; - } - - public int getW() - { - return w; - } -} +package legacy.tests.graph.diamond; + +import ecologylab.serialization.annotations.simpl_scalar; + +public class ClassC +{ + @simpl_scalar + private int u; + + @simpl_scalar + private int w; + + public ClassC() + { + setU(55); + setW(54); + } + + public void setU(int u) + { + this.u = u; + } + + public int getU() + { + return u; + } + + public void setW(int w) + { + this.w = w; + } + + public int getW() + { + return w; + } +} diff --git a/simplTests/test/legacy/tests/graph/diamond/ClassD.java b/simplTests/test/legacy/tests/graph/diamond/ClassD.java index e3f2dacf..f18d0b20 100644 --- a/simplTests/test/legacy/tests/graph/diamond/ClassD.java +++ b/simplTests/test/legacy/tests/graph/diamond/ClassD.java @@ -1,66 +1,66 @@ -package legacy.tests.graph.diamond; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.formatenums.Format; - -public class ClassD implements TestCase -{ - @simpl_composite - private ClassA classA; - - @simpl_composite - private ClassB classB; - - public ClassD() - { - - } - - public ClassD(ClassA classA, ClassB classB) - { - this.setClassA(classA); - this.setClassB(classB); - } - - public void setClassA(ClassA classA) - { - this.classA = classA; - } - - public ClassA getClassA() - { - return classA; - } - - public void setClassB(ClassB classB) - { - this.classB = classB; - } - - public ClassB getClassB() - { - return classB; - } - - @Override - public void runTest() throws SIMPLTranslationException - { - SimplTypesScope.enableGraphSerialization(); - - ClassC classC = new ClassC(); - ClassD test = new ClassD(new ClassA(classC), new ClassB(classC)); - - SimplTypesScope tScope = SimplTypesScope.get("classDTScope", ClassA.class, ClassB.class, - ClassC.class, ClassD.class, ClassX.class); - - TestingUtils.test(test, tScope, Format.XML); - TestingUtils.test(test, tScope, Format.JSON); - TestingUtils.test(test, tScope, Format.TLV); - - SimplTypesScope.disableGraphSerialization(); - } -} +package legacy.tests.graph.diamond; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.formatenums.Format; + +public class ClassD implements TestCase +{ + @simpl_composite + private ClassA classA; + + @simpl_composite + private ClassB classB; + + public ClassD() + { + + } + + public ClassD(ClassA classA, ClassB classB) + { + this.setClassA(classA); + this.setClassB(classB); + } + + public void setClassA(ClassA classA) + { + this.classA = classA; + } + + public ClassA getClassA() + { + return classA; + } + + public void setClassB(ClassB classB) + { + this.classB = classB; + } + + public ClassB getClassB() + { + return classB; + } + + @Override + public void runTest() throws SIMPLTranslationException + { + SimplTypesScope.enableGraphSerialization(); + + ClassC classC = new ClassC(); + ClassD test = new ClassD(new ClassA(classC), new ClassB(classC)); + + SimplTypesScope tScope = SimplTypesScope.get("classDTScope", ClassA.class, ClassB.class, + ClassC.class, ClassD.class, ClassX.class); + + TestingUtils.test(test, tScope, Format.XML); + TestingUtils.test(test, tScope, Format.JSON); + TestingUtils.test(test, tScope, Format.TLV); + + SimplTypesScope.disableGraphSerialization(); + } +} diff --git a/simplTests/test/legacy/tests/graph/diamond/ClassX.java b/simplTests/test/legacy/tests/graph/diamond/ClassX.java index a2c962f3..60198400 100644 --- a/simplTests/test/legacy/tests/graph/diamond/ClassX.java +++ b/simplTests/test/legacy/tests/graph/diamond/ClassX.java @@ -1,38 +1,38 @@ -package legacy.tests.graph.diamond; - -import ecologylab.serialization.annotations.simpl_scalar; - -public class ClassX -{ - @simpl_scalar - private int u; - - @simpl_scalar - private int w; - - public ClassX() - { - setU(44); - setW(33); - } - - public void setU(int u) - { - this.u = u; - } - - public int getU() - { - return u; - } - - public void setW(int w) - { - this.w = w; - } - - public int getW() - { - return w; - } -} +package legacy.tests.graph.diamond; + +import ecologylab.serialization.annotations.simpl_scalar; + +public class ClassX +{ + @simpl_scalar + private int u; + + @simpl_scalar + private int w; + + public ClassX() + { + setU(44); + setW(33); + } + + public void setU(int u) + { + this.u = u; + } + + public int getU() + { + return u; + } + + public void setW(int w) + { + this.w = w; + } + + public int getW() + { + return w; + } +} diff --git a/simplTests/test/legacy/tests/inheritance/BaseClass.java b/simplTests/test/legacy/tests/inheritance/BaseClass.java index 26f434fb..d745d855 100644 --- a/simplTests/test/legacy/tests/inheritance/BaseClass.java +++ b/simplTests/test/legacy/tests/inheritance/BaseClass.java @@ -1,19 +1,20 @@ -package legacy.tests.inheritance; - -import ecologylab.serialization.annotations.simpl_other_tags; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -@simpl_other_tags({"the_field"}) -@simpl_tag("fred") -public class BaseClass -{ - @simpl_tag("new_tag_var") - @simpl_other_tags("other_tag_var") - @simpl_scalar - int var = 3; - - public BaseClass() - { - } -} +package legacy.tests.inheritance; + +import ecologylab.serialization.annotations.simpl_other_tags; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +@simpl_other_tags({"the_field"}) +@simpl_tag("fred") +public class BaseClass +{ + @simpl_tag("new_tag_var") + @simpl_other_tags("other_tag_var") + @simpl_scalar + int var = 3; + + public BaseClass() + { + } + +} diff --git a/simplTests/test/legacy/tests/inheritance/ChildClass1.java b/simplTests/test/legacy/tests/inheritance/ChildClass1.java index 4f83693c..55cbbc5d 100644 --- a/simplTests/test/legacy/tests/inheritance/ChildClass1.java +++ b/simplTests/test/legacy/tests/inheritance/ChildClass1.java @@ -1,17 +1,17 @@ -package legacy.tests.inheritance; - -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -@simpl_inherit -public class ChildClass1 extends BaseClass -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) - int ccvar1 = 1; - - public ChildClass1() - { - } -} +package legacy.tests.inheritance; + +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +@simpl_inherit +public class ChildClass1 extends BaseClass +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) + int ccvar1 = 1; + + public ChildClass1() + { + } +} diff --git a/simplTests/test/legacy/tests/inheritance/ChildClass2.java b/simplTests/test/legacy/tests/inheritance/ChildClass2.java index 02edc4be..533cdf18 100644 --- a/simplTests/test/legacy/tests/inheritance/ChildClass2.java +++ b/simplTests/test/legacy/tests/inheritance/ChildClass2.java @@ -1,18 +1,18 @@ -package legacy.tests.inheritance; - -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -@simpl_inherit -public class ChildClass2 extends BaseClass -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) - int ccvar2 = 2; - - public ChildClass2() - { - } - -} +package legacy.tests.inheritance; + +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +@simpl_inherit +public class ChildClass2 extends BaseClass +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) + int ccvar2 = 2; + + public ChildClass2() + { + } + +} diff --git a/simplTests/test/legacy/tests/inheritance/ContainingClass.java b/simplTests/test/legacy/tests/inheritance/ContainingClass.java index 160d7f50..d98ac300 100644 --- a/simplTests/test/legacy/tests/inheritance/ContainingClass.java +++ b/simplTests/test/legacy/tests/inheritance/ContainingClass.java @@ -1,50 +1,56 @@ -package legacy.tests.inheritance; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_classes; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.formatenums.Format; - -public class ContainingClass implements TestCase -{ - @simpl_classes( - { BaseClass.class, ChildClass1.class, ChildClass2.class }) - @simpl_composite - BaseClass theField; - - public ContainingClass() - { - } - - @Override - public void runTest() throws SIMPLTranslationException - { - SimplTypesScope translationScope = SimplTypesScope.get("containingClassTScope", ContainingClass.class, - ChildClass1.class, ChildClass2.class, BaseClass.class); - - ContainingClass ccb = new ContainingClass(); - ccb.theField = new BaseClass(); - - TestingUtils.test(ccb, translationScope, Format.XML); - TestingUtils.test(ccb, translationScope, Format.JSON); - TestingUtils.test(ccb, translationScope, Format.TLV); - - ContainingClass cc1 = new ContainingClass(); - cc1.theField = new ChildClass1(); - - TestingUtils.test(cc1, translationScope, Format.XML); - TestingUtils.test(cc1, translationScope, Format.JSON); - TestingUtils.test(cc1, translationScope, Format.TLV); - - ContainingClass cc2 = new ContainingClass(); - cc2.theField = new ChildClass2(); - - TestingUtils.test(cc2, translationScope, Format.XML); - TestingUtils.test(cc2, translationScope, Format.JSON); - TestingUtils.test(cc2, translationScope, Format.TLV); - - } -} +package legacy.tests.inheritance; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_classes; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.formatenums.Format; + +public class ContainingClass implements TestCase +{ + @simpl_classes( + { BaseClass.class, ChildClass1.class, ChildClass2.class }) + @simpl_composite + BaseClass theField; + + public ContainingClass() + { + } + + @Override + public void runTest() throws SIMPLTranslationException + { + SimplTypesScope translationScope = SimplTypesScope.get("containingClassTScope", ContainingClass.class, + ChildClass1.class, ChildClass2.class, BaseClass.class); + + ContainingClass ccb = new ContainingClass(); + ccb.theField = new BaseClass(); + + TestingUtils.test(ccb, translationScope, Format.XML); + TestingUtils.test(ccb, translationScope, Format.JSON); + TestingUtils.test(ccb, translationScope, Format.TLV); + + ContainingClass cc1 = new ContainingClass(); + cc1.theField = new ChildClass1(); + + TestingUtils.test(cc1, translationScope, Format.XML); + TestingUtils.test(cc1, translationScope, Format.JSON); + TestingUtils.test(cc1, translationScope, Format.TLV); + + ContainingClass cc2 = new ContainingClass(); + cc2.theField = new ChildClass2(); + + TestingUtils.test(cc2, translationScope, Format.XML); + TestingUtils.test(cc2, translationScope, Format.JSON); + TestingUtils.test(cc2, translationScope, Format.TLV); + + } + + public void setTheField(BaseClass baseClass) { + theField = baseClass; + + } + +} diff --git a/simplTests/test/legacy/tests/items/Container.java b/simplTests/test/legacy/tests/items/Container.java index 065d00ef..8740c301 100644 --- a/simplTests/test/legacy/tests/items/Container.java +++ b/simplTests/test/legacy/tests/items/Container.java @@ -1,73 +1,73 @@ -package legacy.tests.items; - -import java.util.ArrayList; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scope; -import ecologylab.serialization.formatenums.Format; - -public class Container implements TestCase -{ - - @simpl_nowrap - @simpl_scope("itemScope1") - @simpl_collection - ArrayList itemCollection1; - - // @simpl_scope("itemScope2") - // @simpl_collection - ArrayList itemCollection2; - - public Container() - { - - } - - public void populateContainer() - { - itemCollection1 = new ArrayList(); - itemCollection2 = new ArrayList(); - - itemCollection1.add(new ItemOne(1, 1)); - itemCollection1.add(new ItemOne(1, 2)); - itemCollection1.add(new ItemOne(1, 3)); - itemCollection1.add(new ItemTwo("one", 1)); - itemCollection1.add(new ItemTwo("two", 2)); - itemCollection1.add(new ItemTwo("three", 3)); - - itemCollection2.add(new ItemTwo("one", 1)); - itemCollection2.add(new ItemTwo("two", 2)); - itemCollection2.add(new ItemTwo("three", 3)); - itemCollection2.add(new ItemRandom("four", 4)); - itemCollection2.add(new ItemRandom("five", 5)); - itemCollection2.add(new ItemRandom("six", 6)); - } - - @Override - public void runTest() throws SIMPLTranslationException - { - - Container c = new Container(); - c.populateContainer(); - -// TranslationScope itemTranslationScope = TranslationScope.get("itemScope1", ItemBase.class, -// ItemOne.class, ItemTwo.class); -// -// TranslationScope itemTranslationScope2 = TranslationScope.get("itemScope2", ItemBase.class, -// ItemRandom.class, ItemTwo.class); - - SimplTypesScope containerTranslationScope = SimplTypesScope.get("containerTScope", - Container.class, ItemBase.class, ItemOne.class, ItemTwo.class, ItemRandom.class); - - TestingUtils.test(c, containerTranslationScope, Format.XML); - TestingUtils.test(c, containerTranslationScope, Format.JSON); - TestingUtils.test(c, containerTranslationScope, Format.TLV); - - } -} +package legacy.tests.items; + +import java.util.ArrayList; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scope; +import ecologylab.serialization.formatenums.Format; + +public class Container implements TestCase +{ + + @simpl_nowrap + @simpl_scope("itemScope1") + @simpl_collection + ArrayList itemCollection1; + + // @simpl_scope("itemScope2") + // @simpl_collection + ArrayList itemCollection2; + + public Container() + { + + } + + public void populateContainer() + { + itemCollection1 = new ArrayList(); + itemCollection2 = new ArrayList(); + + itemCollection1.add(new ItemOne(1, 1)); + itemCollection1.add(new ItemOne(1, 2)); + itemCollection1.add(new ItemOne(1, 3)); + itemCollection1.add(new ItemTwo("one", 1)); + itemCollection1.add(new ItemTwo("two", 2)); + itemCollection1.add(new ItemTwo("three", 3)); + + itemCollection2.add(new ItemTwo("one", 1)); + itemCollection2.add(new ItemTwo("two", 2)); + itemCollection2.add(new ItemTwo("three", 3)); + itemCollection2.add(new ItemRandom("four", 4)); + itemCollection2.add(new ItemRandom("five", 5)); + itemCollection2.add(new ItemRandom("six", 6)); + } + + @Override + public void runTest() throws SIMPLTranslationException + { + + Container c = new Container(); + c.populateContainer(); + +// TranslationScope itemTranslationScope = TranslationScope.get("itemScope1", ItemBase.class, +// ItemOne.class, ItemTwo.class); +// +// TranslationScope itemTranslationScope2 = TranslationScope.get("itemScope2", ItemBase.class, +// ItemRandom.class, ItemTwo.class); + + SimplTypesScope containerTranslationScope = SimplTypesScope.get("containerTScope", + Container.class, ItemBase.class, ItemOne.class, ItemTwo.class, ItemRandom.class); + + TestingUtils.test(c, containerTranslationScope, Format.XML); + TestingUtils.test(c, containerTranslationScope, Format.JSON); + TestingUtils.test(c, containerTranslationScope, Format.TLV); + + } +} diff --git a/simplTests/test/legacy/tests/items/ItemBase.java b/simplTests/test/legacy/tests/items/ItemBase.java index a6adf4d9..b5650f76 100644 --- a/simplTests/test/legacy/tests/items/ItemBase.java +++ b/simplTests/test/legacy/tests/items/ItemBase.java @@ -1,14 +1,14 @@ -package legacy.tests.items; - -import ecologylab.serialization.annotations.simpl_scalar; - -public class ItemBase -{ - @simpl_scalar - int var; - - public ItemBase() - { - - } -} +package legacy.tests.items; + +import ecologylab.serialization.annotations.simpl_scalar; + +public class ItemBase +{ + @simpl_scalar + int var; + + public ItemBase() + { + + } +} diff --git a/simplTests/test/legacy/tests/items/ItemOne.java b/simplTests/test/legacy/tests/items/ItemOne.java index 24f545b7..14e422b4 100644 --- a/simplTests/test/legacy/tests/items/ItemOne.java +++ b/simplTests/test/legacy/tests/items/ItemOne.java @@ -1,23 +1,23 @@ -package legacy.tests.items; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -@simpl_inherit -public class ItemOne extends ItemBase -{ - @simpl_scalar - int testing; - - - public ItemOne() - { - - } - - public ItemOne(int testing, int var) - { - this.testing = testing; - this.var = var; - } -} +package legacy.tests.items; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +@simpl_inherit +public class ItemOne extends ItemBase +{ + @simpl_scalar + int testing; + + + public ItemOne() + { + + } + + public ItemOne(int testing, int var) + { + this.testing = testing; + this.var = var; + } +} diff --git a/simplTests/test/legacy/tests/items/ItemRandom.java b/simplTests/test/legacy/tests/items/ItemRandom.java index 7a0f4a0d..e75f1f6a 100644 --- a/simplTests/test/legacy/tests/items/ItemRandom.java +++ b/simplTests/test/legacy/tests/items/ItemRandom.java @@ -1,22 +1,22 @@ -package legacy.tests.items; - -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -@simpl_tag("item_one") -public class ItemRandom extends ItemBase -{ - @simpl_scalar - String randomString; - - public ItemRandom() - { - - } - - public ItemRandom(String randomString, int var) - { - this.randomString = randomString; - this.var = var; - } -} +package legacy.tests.items; + +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +@simpl_tag("item_one") +public class ItemRandom extends ItemBase +{ + @simpl_scalar + String randomString; + + public ItemRandom() + { + + } + + public ItemRandom(String randomString, int var) + { + this.randomString = randomString; + this.var = var; + } +} diff --git a/simplTests/test/legacy/tests/items/ItemTwo.java b/simplTests/test/legacy/tests/items/ItemTwo.java index f849146c..28faa3e9 100644 --- a/simplTests/test/legacy/tests/items/ItemTwo.java +++ b/simplTests/test/legacy/tests/items/ItemTwo.java @@ -1,22 +1,22 @@ -package legacy.tests.items; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -@simpl_inherit -public class ItemTwo extends ItemBase -{ - @simpl_scalar - String testString; - - public ItemTwo() - { - - } - - public ItemTwo(String testString, int var) - { - this.testString = testString; - this.var = var; - } -} +package legacy.tests.items; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +@simpl_inherit +public class ItemTwo extends ItemBase +{ + @simpl_scalar + String testString; + + public ItemTwo() + { + + } + + public ItemTwo(String testString, int var) + { + this.testString = testString; + this.var = var; + } +} diff --git a/simplTests/test/legacy/tests/maps/ClassDes.java b/simplTests/test/legacy/tests/maps/ClassDes.java index 9722a73c..9b6feff3 100644 --- a/simplTests/test/legacy/tests/maps/ClassDes.java +++ b/simplTests/test/legacy/tests/maps/ClassDes.java @@ -1,36 +1,36 @@ -package legacy.tests.maps; - -import java.util.HashMap; - -import ecologylab.serialization.annotations.simpl_map; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.element.IMappable; - -public class ClassDes implements IMappable -{ - @simpl_scalar - public String tagName; - - @simpl_nowrap - @simpl_map("field_descriptor") - public HashMap fieldDescriptorsByTagName; - - public ClassDes() - { - tagName = ""; - fieldDescriptorsByTagName = new HashMap(); - } - - public ClassDes(String tagName) - { - this.tagName = tagName; - fieldDescriptorsByTagName = new HashMap(); - } - - @Override - public String key() - { - return tagName; - } -} +package legacy.tests.maps; + +import java.util.HashMap; + +import ecologylab.serialization.annotations.simpl_map; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.element.IMappable; + +public class ClassDes implements IMappable +{ + @simpl_scalar + public String tagName; + + @simpl_nowrap + @simpl_map("field_descriptor") + public HashMap fieldDescriptorsByTagName; + + public ClassDes() + { + tagName = ""; + fieldDescriptorsByTagName = new HashMap(); + } + + public ClassDes(String tagName) + { + this.tagName = tagName; + fieldDescriptorsByTagName = new HashMap(); + } + + @Override + public String key() + { + return tagName; + } +} diff --git a/simplTests/test/legacy/tests/maps/FieldDes.java b/simplTests/test/legacy/tests/maps/FieldDes.java index bce65940..415402f4 100644 --- a/simplTests/test/legacy/tests/maps/FieldDes.java +++ b/simplTests/test/legacy/tests/maps/FieldDes.java @@ -1,26 +1,26 @@ -package legacy.tests.maps; - -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.types.element.IMappable; - -public class FieldDes implements IMappable -{ - @simpl_scalar - public String fieldName; - - public FieldDes() - { - fieldName = ""; - } - - public FieldDes(String fieldName) - { - this.fieldName = fieldName; - } - - @Override - public String key() - { - return this.fieldName; - } -} +package legacy.tests.maps; + +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.types.element.IMappable; + +public class FieldDes implements IMappable +{ + @simpl_scalar + public String fieldName; + + public FieldDes() + { + fieldName = ""; + } + + public FieldDes(String fieldName) + { + this.fieldName = fieldName; + } + + @Override + public String key() + { + return this.fieldName; + } +} diff --git a/simplTests/test/legacy/tests/maps/TestingMapsWithinMaps.java b/simplTests/test/legacy/tests/maps/TestingMapsWithinMaps.java index 8ab75443..e78e5f3b 100644 --- a/simplTests/test/legacy/tests/maps/TestingMapsWithinMaps.java +++ b/simplTests/test/legacy/tests/maps/TestingMapsWithinMaps.java @@ -1,51 +1,51 @@ -package legacy.tests.maps; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.Format; - -public class TestingMapsWithinMaps implements TestCase -{ - public static TranslationS createObject() - { - TranslationS trans = new TranslationS(); - - ClassDes cd1 = new ClassDes("cd1"); - - cd1.fieldDescriptorsByTagName.put("fd1_cd1", new FieldDes("fd1_cd1")); - cd1.fieldDescriptorsByTagName.put("fd2_cd1", new FieldDes("fd2_cd1")); - cd1.fieldDescriptorsByTagName.put("fd3_cd1", new FieldDes("fd3_cd1")); - - ClassDes cd2 = new ClassDes("cd2"); - cd2.fieldDescriptorsByTagName.put("fd1_cd2", new FieldDes("fd1_cd2")); - cd2.fieldDescriptorsByTagName.put("fd2_cd2", new FieldDes("fd2_cd2")); - cd2.fieldDescriptorsByTagName.put("fd3_cd2", new FieldDes("fd3_cd2")); - - trans.entriesByTag.put("cd1", cd1); - trans.entriesByTag.put("cd2", cd2); - - return trans; - } - - @Override - public void runTest() throws SIMPLTranslationException - { -// TranslationScope.enableGraphSerialization(); - - TranslationS test = createObject(); - SimplTypesScope tScope = SimplTypesScope.get("testingMapWithinMapsTScope", TranslationS.class, ClassDes.class, - FieldDes.class); - - SimplTypesScope.enableGraphSerialization(); - TestingUtils.serializeSimplTypesScope(tScope, "testingMapWithinMapsTScope", Format.JSON); - - TestingUtils.test(test, tScope, Format.XML); - TestingUtils.test(test, tScope, Format.JSON); - TestingUtils.test(test, tScope, Format.TLV); - -// TranslationScope.disableGraphSerialization(); - - } -} +package legacy.tests.maps; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; + +public class TestingMapsWithinMaps implements TestCase +{ + public static TranslationS createObject() + { + TranslationS trans = new TranslationS(); + + ClassDes cd1 = new ClassDes("cd1"); + + cd1.fieldDescriptorsByTagName.put("fd1_cd1", new FieldDes("fd1_cd1")); + cd1.fieldDescriptorsByTagName.put("fd2_cd1", new FieldDes("fd2_cd1")); + cd1.fieldDescriptorsByTagName.put("fd3_cd1", new FieldDes("fd3_cd1")); + + ClassDes cd2 = new ClassDes("cd2"); + cd2.fieldDescriptorsByTagName.put("fd1_cd2", new FieldDes("fd1_cd2")); + cd2.fieldDescriptorsByTagName.put("fd2_cd2", new FieldDes("fd2_cd2")); + cd2.fieldDescriptorsByTagName.put("fd3_cd2", new FieldDes("fd3_cd2")); + + trans.entriesByTag.put("cd1", cd1); + trans.entriesByTag.put("cd2", cd2); + + return trans; + } + + @Override + public void runTest() throws SIMPLTranslationException + { +// TranslationScope.enableGraphSerialization(); + + TranslationS test = createObject(); + SimplTypesScope tScope = SimplTypesScope.get("testingMapWithinMapsTScope", TranslationS.class, ClassDes.class, + FieldDes.class); + + SimplTypesScope.enableGraphSerialization(); + TestingUtils.serializeSimplTypesScope(tScope, "testingMapWithinMapsTScope", Format.JSON); + + TestingUtils.test(test, tScope, Format.XML); + TestingUtils.test(test, tScope, Format.JSON); + TestingUtils.test(test, tScope, Format.TLV); + +// TranslationScope.disableGraphSerialization(); + + } +} diff --git a/simplTests/test/legacy/tests/maps/TranslationS.java b/simplTests/test/legacy/tests/maps/TranslationS.java index 17b190ca..f9e139f3 100644 --- a/simplTests/test/legacy/tests/maps/TranslationS.java +++ b/simplTests/test/legacy/tests/maps/TranslationS.java @@ -1,19 +1,19 @@ -package legacy.tests.maps; - -import java.util.HashMap; - -import ecologylab.serialization.annotations.simpl_map; -import ecologylab.serialization.annotations.simpl_nowrap; - -public class TranslationS -{ - @simpl_nowrap - @simpl_map("class_descriptor") - public HashMap entriesByTag; - - public TranslationS() - { - entriesByTag = new HashMap(); - } - -} +package legacy.tests.maps; + +import java.util.HashMap; + +import ecologylab.serialization.annotations.simpl_map; +import ecologylab.serialization.annotations.simpl_nowrap; + +public class TranslationS +{ + @simpl_nowrap + @simpl_map("class_descriptor") + public HashMap entriesByTag; + + public TranslationS() + { + entriesByTag = new HashMap(); + } + +} diff --git a/simplTests/test/legacy/tests/net/ParsedURLMapTest.java b/simplTests/test/legacy/tests/net/ParsedURLMapTest.java index d1d461a2..15436866 100644 --- a/simplTests/test/legacy/tests/net/ParsedURLMapTest.java +++ b/simplTests/test/legacy/tests/net/ParsedURLMapTest.java @@ -1,36 +1,36 @@ -package legacy.tests.net; - -import java.util.HashMap; - -import legacy.tests.TestCase; - -import ecologylab.generic.Debug; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.SIMPLTranslationException; - -public class ParsedURLMapTest extends Debug implements TestCase -{ - private HashMap urlSpanMap; - - public ParsedURLMapTest() - { - } - - @Override - public void runTest() throws SIMPLTranslationException - { - urlSpanMap = new HashMap(); - - ParsedURL purl = ParsedURL.getAbsolute("http://dl.acm.org/citation.cfm?id=1871437.1871580"); - if (purl == null) - return; - - urlSpanMap.put(purl, (int)(Math.random()*100)); - if (!urlSpanMap.containsKey(purl)) - warning("containsKey() fails for ParsedURL Map"); - if (urlSpanMap.get(purl) == null) - warning("get() fails for ParsedURL Map"); - - debug("containsKey() and get() tested for ParsedURL Maps"); - } -} +package legacy.tests.net; + +import java.util.HashMap; + +import legacy.tests.TestCase; + +import ecologylab.generic.Debug; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.SIMPLTranslationException; + +public class ParsedURLMapTest extends Debug implements TestCase +{ + private HashMap urlSpanMap; + + public ParsedURLMapTest() + { + } + + @Override + public void runTest() throws SIMPLTranslationException + { + urlSpanMap = new HashMap(); + + ParsedURL purl = ParsedURL.getAbsolute("http://dl.acm.org/citation.cfm?id=1871437.1871580"); + if (purl == null) + return; + + urlSpanMap.put(purl, (int)(Math.random()*100)); + if (!urlSpanMap.containsKey(purl)) + warning("containsKey() fails for ParsedURL Map"); + if (urlSpanMap.get(purl) == null) + warning("get() fails for ParsedURL Map"); + + debug("containsKey() and get() tested for ParsedURL Maps"); + } +} diff --git a/simplTests/test/legacy/tests/person/Faculty.java b/simplTests/test/legacy/tests/person/Faculty.java index 8e449dbf..e548c81a 100644 --- a/simplTests/test/legacy/tests/person/Faculty.java +++ b/simplTests/test/legacy/tests/person/Faculty.java @@ -1,51 +1,51 @@ -package legacy.tests.person; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; - -@simpl_inherit -public -class Faculty extends Person implements TestCase -{ - @simpl_scalar - private String designation; - - public void setStuNum(String sn) - { - designation = sn; - } - - public String getStuNum() - { - return designation; - } - - public Faculty() - { - super(); - this.designation = ""; - } - - public Faculty(String name, String designation) - { - super(name); - this.designation = designation; - } - - @Override - public void runTest() throws SIMPLTranslationException - { - Faculty f = new Faculty("andruid", "professor"); - - SimplTypesScope translationScope = SimplTypesScope.get("facultyTScope", Person.class, Faculty.class); - - TestingUtils.test(f, translationScope, Format.XML); - TestingUtils.test(f, translationScope, Format.JSON); - TestingUtils.test(f, translationScope, Format.TLV); - } -} +package legacy.tests.person; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +@simpl_inherit +public +class Faculty extends Person implements TestCase +{ + @simpl_scalar + private String designation; + + public void setStuNum(String sn) + { + designation = sn; + } + + public String getStuNum() + { + return designation; + } + + public Faculty() + { + super(); + this.designation = ""; + } + + public Faculty(String name, String designation) + { + super(name); + this.designation = designation; + } + + @Override + public void runTest() throws SIMPLTranslationException + { + Faculty f = new Faculty("andruid", "professor"); + + SimplTypesScope translationScope = SimplTypesScope.get("facultyTScope", Person.class, Faculty.class); + + TestingUtils.test(f, translationScope, Format.XML); + TestingUtils.test(f, translationScope, Format.JSON); + TestingUtils.test(f, translationScope, Format.TLV); + } +} diff --git a/simplTests/test/legacy/tests/person/Person.java b/simplTests/test/legacy/tests/person/Person.java index 35860d83..fc790b01 100644 --- a/simplTests/test/legacy/tests/person/Person.java +++ b/simplTests/test/legacy/tests/person/Person.java @@ -1,53 +1,53 @@ -package legacy.tests.person; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.types.element.IMappable; - -public class Person implements TestCase, IMappable -{ - @simpl_scalar - private String name; - - public Person() - { - name = ""; - } - - public Person(String name) - { - this.name = name; - } - - public void setName(String n) - { - name = n; - } - - public String getName() - { - return name; - } - - @Override - public void runTest() throws SIMPLTranslationException - { - Person p = new Person("nabeel"); - - SimplTypesScope translationScope = SimplTypesScope.get("personTScope", Person.class); - - TestingUtils.test(p, translationScope, Format.XML); - TestingUtils.test(p, translationScope, Format.JSON); - TestingUtils.test(p, translationScope, Format.TLV); - } - - @Override - public String key() - { - return name; - } -} +package legacy.tests.person; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.types.element.IMappable; + +public class Person implements TestCase, IMappable +{ + @simpl_scalar + private String name; + + public Person() + { + name = ""; + } + + public Person(String name) + { + this.name = name; + } + + public void setName(String n) + { + name = n; + } + + public String getName() + { + return name; + } + + @Override + public void runTest() throws SIMPLTranslationException + { + Person p = new Person("nabeel"); + + SimplTypesScope translationScope = SimplTypesScope.get("personTScope", Person.class); + + TestingUtils.test(p, translationScope, Format.XML); + TestingUtils.test(p, translationScope, Format.JSON); + TestingUtils.test(p, translationScope, Format.TLV); + } + + @Override + public String key() + { + return name; + } +} diff --git a/simplTests/test/legacy/tests/person/PersonDirectory.java b/simplTests/test/legacy/tests/person/PersonDirectory.java index 8d3f599f..a6af7344 100644 --- a/simplTests/test/legacy/tests/person/PersonDirectory.java +++ b/simplTests/test/legacy/tests/person/PersonDirectory.java @@ -1,50 +1,52 @@ -package legacy.tests.person; - -import java.util.ArrayList; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_classes; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.formatenums.Format; - -public class PersonDirectory implements TestCase -{ - @simpl_classes( - { Student.class, Faculty.class }) - @simpl_collection - private ArrayList persons = new ArrayList(); - - public PersonDirectory() - { - persons = new ArrayList(); - } - - public void initializeDirectory() - { - persons.add(new Student("nabeel", "234342")); - persons.add(new Student("yin", "423423")); - persons.add(new Faculty("andruid", "prof")); - persons.add(new Student("bill", "4234234")); - persons.add(new Student("sashi", "5454")); - persons.add(new Student("jon", "656565")); - - } - - @Override - public void runTest() throws SIMPLTranslationException - { - PersonDirectory p = new PersonDirectory(); - p.initializeDirectory(); - - SimplTypesScope translationScope = SimplTypesScope.get("personDirectoryTScope", Person.class, - Faculty.class, Student.class, PersonDirectory.class); - - TestingUtils.test(p, translationScope, Format.XML); - TestingUtils.test(p, translationScope, Format.JSON); - TestingUtils.test(p, translationScope, Format.TLV); - } -} +package legacy.tests.person; + +import java.util.ArrayList; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_classes; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.formatenums.Format; + +public class PersonDirectory implements TestCase +{ + @simpl_classes( + { Student.class, Faculty.class }) + @simpl_collection + private ArrayList persons = new ArrayList(); + + public PersonDirectory() + { + persons = new ArrayList(); + } + + public void initializeDirectory() + { + persons.add(new Student("nabeel", "234342")); + persons.add(new Student("yin", "423423")); + persons.add(new Faculty("andruid", "prof")); + persons.add(new Student("bill", "4234234")); + persons.add(new Student("sashi", "5454")); + persons.add(new Student("jon", "656565")); + + } + + @Override + public void runTest() throws SIMPLTranslationException + { + PersonDirectory p = new PersonDirectory(); + p.initializeDirectory(); + + SimplTypesScope translationScope = SimplTypesScope.get("personDirectoryTScope", Person.class, + Faculty.class, Student.class, PersonDirectory.class); + + TestingUtils.test(p, translationScope, Format.XML); + TestingUtils.test(p, translationScope, Format.JSON); + TestingUtils.test(p, translationScope, Format.TLV); + } + + +} diff --git a/simplTests/test/legacy/tests/person/Student.java b/simplTests/test/legacy/tests/person/Student.java index 34398a49..5d985eaf 100644 --- a/simplTests/test/legacy/tests/person/Student.java +++ b/simplTests/test/legacy/tests/person/Student.java @@ -1,49 +1,49 @@ -package legacy.tests.person; - -import legacy.tests.TestingUtils; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; - -@simpl_inherit -public class Student extends Person -{ - @simpl_scalar - private String stuNum; - - public void setStuNum(String sn) - { - stuNum = sn; - } - - public String getStuNum() - { - return stuNum; - } - - public Student() - { - super(); - this.stuNum = ""; - } - - public Student(String name, String stuNum) - { - super(name); - this.stuNum = stuNum; - } - - @Override - public void runTest() throws SIMPLTranslationException - { - Student s = new Student("nabeel", "12343434"); - - SimplTypesScope translationScope = SimplTypesScope.get("studentTScope", Person.class, Student.class); - - TestingUtils.test(s, translationScope, Format.XML); - TestingUtils.test(s, translationScope, Format.JSON); - TestingUtils.test(s, translationScope, Format.TLV); - } -} +package legacy.tests.person; + +import legacy.tests.TestingUtils; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +@simpl_inherit +public class Student extends Person +{ + @simpl_scalar + private String stuNum; + + public void setStuNum(String sn) + { + stuNum = sn; + } + + public String getStuNum() + { + return stuNum; + } + + public Student() + { + super(); + this.stuNum = ""; + } + + public Student(String name, String stuNum) + { + super(name); + this.stuNum = stuNum; + } + + @Override + public void runTest() throws SIMPLTranslationException + { + Student s = new Student("nabeel", "12343434"); + + SimplTypesScope translationScope = SimplTypesScope.get("studentTScope", Person.class, Student.class); + + TestingUtils.test(s, translationScope, Format.XML); + TestingUtils.test(s, translationScope, Format.JSON); + TestingUtils.test(s, translationScope, Format.TLV); + } +} diff --git a/simplTests/test/legacy/tests/person/StudentDirectory.java b/simplTests/test/legacy/tests/person/StudentDirectory.java index d05ecca1..e6f9cd5a 100644 --- a/simplTests/test/legacy/tests/person/StudentDirectory.java +++ b/simplTests/test/legacy/tests/person/StudentDirectory.java @@ -1,68 +1,68 @@ -package legacy.tests.person; - -import java.util.ArrayList; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; - -public class StudentDirectory implements TestCase -{ - @simpl_nowrap - @simpl_collection("student") - private ArrayList students = new ArrayList(); - - - @simpl_hints(Hint.XML_LEAF) - @simpl_scalar - String test = null; - - public StudentDirectory() - { - this.setStudents(new ArrayList()); - } - - public void setStudents(ArrayList students) - { - this.students = students; - } - - public ArrayList getStudents() - { - return students; - } - - public void initializeDirectory() - { - students.add(new Student("nabeel", "234342")); - students.add(new Student("yin", "423423")); - students.add(new Student("bill", "4234234")); - students.add(new Student("sashi", "5454")); - students.add(new Student("jon", "656565")); - - test = "nabel"; - - } - - @Override - public void runTest() throws SIMPLTranslationException - { - StudentDirectory s = new StudentDirectory(); - s.initializeDirectory(); - - SimplTypesScope translationScope = SimplTypesScope.get("studentDirectoryTScope", Person.class, Student.class, - StudentDirectory.class); - - TestingUtils.test(s, translationScope, Format.XML); - TestingUtils.test(s, translationScope, Format.JSON); - TestingUtils.test(s, translationScope, Format.TLV); - } +package legacy.tests.person; + +import java.util.ArrayList; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +public class StudentDirectory implements TestCase +{ + @simpl_nowrap + @simpl_collection("student") + private ArrayList students = new ArrayList(); + + + @simpl_hints(Hint.XML_LEAF) + @simpl_scalar + String test = null; + + public StudentDirectory() + { + this.setStudents(new ArrayList()); + } + + public void setStudents(ArrayList students) + { + this.students = students; + } + + public ArrayList getStudents() + { + return students; + } + + public void initializeDirectory() + { + students.add(new Student("nabeel", "234342")); + students.add(new Student("yin", "423423")); + students.add(new Student("bill", "4234234")); + students.add(new Student("sashi", "5454")); + students.add(new Student("jon", "656565")); + + test = "nabel"; + + } + + @Override + public void runTest() throws SIMPLTranslationException + { + StudentDirectory s = new StudentDirectory(); + s.initializeDirectory(); + + SimplTypesScope translationScope = SimplTypesScope.get("studentDirectoryTScope", Person.class, Student.class, + StudentDirectory.class); + + TestingUtils.test(s, translationScope, Format.XML); + TestingUtils.test(s, translationScope, Format.JSON); + TestingUtils.test(s, translationScope, Format.TLV); + } } \ No newline at end of file diff --git a/simplTests/test/legacy/tests/rss/Channel.java b/simplTests/test/legacy/tests/rss/Channel.java index e4b776e6..d27a71cc 100644 --- a/simplTests/test/legacy/tests/rss/Channel.java +++ b/simplTests/test/legacy/tests/rss/Channel.java @@ -1,31 +1,31 @@ -//Channel.java - -package legacy.tests.rss; - -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; - -public class Channel extends ElementState -{ - @simpl_nowrap - @simpl_collection("item") - ArrayList items; - - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; - - public Channel() { } - - public ArrayList getItems() - { - return items; - } -} +//Channel.java + +package legacy.tests.rss; + +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; + +public class Channel extends ElementState +{ + @simpl_nowrap + @simpl_collection("item") + ArrayList items; + + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; + + public Channel() { } + + public ArrayList getItems() + { + return items; + } +} diff --git a/simplTests/test/legacy/tests/rss/Item.java b/simplTests/test/legacy/tests/rss/Item.java index 02a11816..8fb3ede5 100644 --- a/simplTests/test/legacy/tests/rss/Item.java +++ b/simplTests/test/legacy/tests/rss/Item.java @@ -1,50 +1,50 @@ -//Item.java - -package legacy.tests.rss; - -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; - -public class Item extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL guid; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String author; - -// @simpl_nowrap -// @simpl_collection("category") - ArrayList categorySet; - - public Item() {} - - public void setTitle(String string) - { - title = string; - } - - public void setDescription(String string) - { - description = string; - - } - - public void setAuthor(String string) - { - author = string; - - } - - public void setLink(ParsedURL parsedURL) - { - link = parsedURL; - } -} +//Item.java + +package legacy.tests.rss; + +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; + +public class Item extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL guid; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String author; + +// @simpl_nowrap +// @simpl_collection("category") + ArrayList categorySet; + + public Item() {} + + public void setTitle(String string) + { + title = string; + } + + public void setDescription(String string) + { + description = string; + + } + + public void setAuthor(String string) + { + author = string; + + } + + public void setLink(ParsedURL parsedURL) + { + link = parsedURL; + } +} diff --git a/simplTests/test/legacy/tests/rss/Rss.java b/simplTests/test/legacy/tests/rss/Rss.java index 3cb90728..d4c12030 100644 --- a/simplTests/test/legacy/tests/rss/Rss.java +++ b/simplTests/test/legacy/tests/rss/Rss.java @@ -1,89 +1,89 @@ -// RssState.java - -package legacy.tests.rss; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; - -public class Rss implements TestCase -{ - @simpl_scalar - float version; - - @simpl_composite - Channel channel; - - public Rss() - { - } - - public Channel getChannel() - { - return channel; - } - - @Override - public void runTest() throws SIMPLTranslationException - { - SimplTypesScope translationScope = SimplTypesScope.get("rssTScope", Rss.class, Channel.class, - Item.class); - -// TestingUtils.generateCocoaClasses(translationScope); - - Rss rssState = new Rss(); - Channel channel = new Channel(); - Item item1 = new Item(); - Item item2 = new Item(); - - ArrayList categorySet = new ArrayList(); - - rssState.version = 1.0f; - - channel.title = "testTitle"; - channel.description = "testDescription"; - - try - { - channel.link = new ParsedURL(new URL("http://www.google.com")); - } - catch (MalformedURLException e) - { - e.printStackTrace(); - } - - categorySet.add("category1"); - categorySet.add("category2"); - - item1.title = "testItem1"; - item1.description = "testItem1Description"; - item1.categorySet = categorySet; - - item2.title = "testItem2"; - item2.description = "testItem2Description"; - - ArrayList items = new ArrayList(); - items.add(item1); - items.add(item2); - - channel.items = items; - rssState.channel = channel; - - TestingUtils.test(rssState, translationScope, Format.XML); - TestingUtils.test(rssState, translationScope, Format.JSON); - TestingUtils.test(rssState, translationScope, Format.TLV); - - } -} +// RssState.java + +package legacy.tests.rss; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +public class Rss implements TestCase +{ + @simpl_scalar + float version; + + @simpl_composite + Channel channel; + + public Rss() + { + } + + public Channel getChannel() + { + return channel; + } + + @Override + public void runTest() throws SIMPLTranslationException + { + SimplTypesScope translationScope = SimplTypesScope.get("rssTScope", Rss.class, Channel.class, + Item.class); + +// TestingUtils.generateCocoaClasses(translationScope); + + Rss rssState = new Rss(); + Channel channel = new Channel(); + Item item1 = new Item(); + Item item2 = new Item(); + + ArrayList categorySet = new ArrayList(); + + rssState.version = 1.0f; + + channel.title = "testTitle"; + channel.description = "testDescription"; + + try + { + channel.link = new ParsedURL(new URL("http://www.google.com")); + } + catch (MalformedURLException e) + { + e.printStackTrace(); + } + + categorySet.add("category1"); + categorySet.add("category2"); + + item1.title = "testItem1"; + item1.description = "testItem1Description"; + item1.categorySet = categorySet; + + item2.title = "testItem2"; + item2.description = "testItem2Description"; + + ArrayList items = new ArrayList(); + items.add(item1); + items.add(item2); + + channel.items = items; + rssState.channel = channel; + + TestingUtils.test(rssState, translationScope, Format.XML); + TestingUtils.test(rssState, translationScope, Format.JSON); + TestingUtils.test(rssState, translationScope, Format.TLV); + + } +} diff --git a/simplTests/test/legacy/tests/scalar/Enum.java b/simplTests/test/legacy/tests/scalar/Enum.java index f29640e0..5dc48bfa 100644 --- a/simplTests/test/legacy/tests/scalar/Enum.java +++ b/simplTests/test/legacy/tests/scalar/Enum.java @@ -1,40 +1,40 @@ -package legacy.tests.scalar; - -import static org.junit.Assert.*; -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; -import legacy.tests.circle.Circle; -import legacy.tests.circle.Point; - -import org.junit.Test; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; - - -public class Enum implements TestCase { - - @simpl_scalar - NonsenseEnum p; - public Enum() - { - - } - public Enum(NonsenseEnum pile) { - p = pile; - } - - @Override - public void runTest() throws SIMPLTranslationException { - - Enum c = new Enum(NonsenseEnum.BUCKLE_MY_SHOES); - SimplTypesScope t = SimplTypesScope.get("enumTest", Enum.class); - SimplTypesScope.enableGraphSerialization(); - - TestingUtils.test(c, t, Format.XML); - TestingUtils.test(c, t, Format.JSON); - } - -} +package legacy.tests.scalar; + +import static org.junit.Assert.*; +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import legacy.tests.circle.Circle; +import legacy.tests.circle.Point; + +import org.junit.Test; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + + +public class Enum implements TestCase { + + @simpl_scalar + NonsenseEnum p; + public Enum() + { + + } + public Enum(NonsenseEnum pile) { + p = pile; + } + + @Override + public void runTest() throws SIMPLTranslationException { + + Enum c = new Enum(NonsenseEnum.BUCKLE_MY_SHOES); + SimplTypesScope t = SimplTypesScope.get("enumTest", Enum.class); + SimplTypesScope.enableGraphSerialization(); + + TestingUtils.test(c, t, Format.XML); + TestingUtils.test(c, t, Format.JSON); + } + +} diff --git a/simplTests/test/legacy/tests/scalar/EnumCollection.java b/simplTests/test/legacy/tests/scalar/EnumCollection.java index 887826b3..abf229b5 100644 --- a/simplTests/test/legacy/tests/scalar/EnumCollection.java +++ b/simplTests/test/legacy/tests/scalar/EnumCollection.java @@ -1,48 +1,48 @@ -package legacy.tests.scalar; - -import java.util.ArrayList; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.FieldUsage; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.formatenums.Format; - -public class EnumCollection implements TestCase{ - - @simpl_collection("enums") - ArrayList collectionOfEnums; - - public EnumCollection() - { - - } - - public EnumCollection(ArrayList ce) { - collectionOfEnums = ce; - } - - @Override - public void runTest() throws SIMPLTranslationException { - - ArrayList ce = new ArrayList(); - ce.add(new Enum(NonsenseEnum.BUCKLE_MY_SHOES)); - ce.add(new Enum(NonsenseEnum.TWO)); - ce.add(new Enum(NonsenseEnum.ONE)); - - EnumCollection c = new EnumCollection(ce); - - SimplTypesScope t = SimplTypesScope.get("enumCollectionTest",EnumCollection.class); - SimplTypesScope.enableGraphSerialization(); - - TestingUtils.test(c, t, Format.XML); - TestingUtils.test(c, t, Format.JSON); - TestingUtils.test(c, t, Format.TLV); - - } - - -} +package legacy.tests.scalar; + +import java.util.ArrayList; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.FieldUsage; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.formatenums.Format; + +public class EnumCollection implements TestCase{ + + @simpl_collection("enums") + ArrayList collectionOfEnums; + + public EnumCollection() + { + + } + + public EnumCollection(ArrayList ce) { + collectionOfEnums = ce; + } + + @Override + public void runTest() throws SIMPLTranslationException { + + ArrayList ce = new ArrayList(); + ce.add(new Enum(NonsenseEnum.BUCKLE_MY_SHOES)); + ce.add(new Enum(NonsenseEnum.TWO)); + ce.add(new Enum(NonsenseEnum.ONE)); + + EnumCollection c = new EnumCollection(ce); + + SimplTypesScope t = SimplTypesScope.get("enumCollectionTest",EnumCollection.class); + SimplTypesScope.enableGraphSerialization(); + + TestingUtils.test(c, t, Format.XML); + TestingUtils.test(c, t, Format.JSON); + TestingUtils.test(c, t, Format.TLV); + + } + + +} diff --git a/simplTests/test/legacy/tests/scalar/EnumOfFieldUsageCollection.java b/simplTests/test/legacy/tests/scalar/EnumOfFieldUsageCollection.java index 2a3dfcbc..805f3115 100644 --- a/simplTests/test/legacy/tests/scalar/EnumOfFieldUsageCollection.java +++ b/simplTests/test/legacy/tests/scalar/EnumOfFieldUsageCollection.java @@ -1,51 +1,51 @@ -package legacy.tests.scalar; - -import java.util.ArrayList; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.FieldUsage; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.Format; - -public class EnumOfFieldUsageCollection implements TestCase{//Test no render - @simpl_scalar - int number; - - @simpl_collection("numnum") - ArrayList collectionOfFieldUseage; - - public EnumOfFieldUsageCollection() - { - number = 4; - } - - public EnumOfFieldUsageCollection(ArrayList ce) { - collectionOfFieldUseage = ce; - number = 4; - } - - @Override - public void runTest() throws SIMPLTranslationException { - - ArrayList ce = new ArrayList(); - ce.add(FieldUsage.CODE_GENERATION); - ce.add(FieldUsage.PERSISTENCE); - - EnumOfFieldUsageCollection c = new EnumOfFieldUsageCollection(ce); - - SimplTypesScope t = SimplTypesScope.get("enumCollectionTest",EnumOfFieldUsageCollection.class); - SimplTypesScope.enableGraphSerialization(); - - TestingUtils.test(c, t, Format.XML); - TestingUtils.test(c, t, Format.JSON); - TestingUtils.test(c, t, Format.TLV); - - } - - -} +package legacy.tests.scalar; + +import java.util.ArrayList; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.FieldUsage; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +public class EnumOfFieldUsageCollection implements TestCase{//Test no render + @simpl_scalar + int number; + + @simpl_collection("numnum") + ArrayList collectionOfFieldUseage; + + public EnumOfFieldUsageCollection() + { + number = 4; + } + + public EnumOfFieldUsageCollection(ArrayList ce) { + collectionOfFieldUseage = ce; + number = 4; + } + + @Override + public void runTest() throws SIMPLTranslationException { + + ArrayList ce = new ArrayList(); + ce.add(FieldUsage.CODE_GENERATION); + ce.add(FieldUsage.PERSISTENCE); + + EnumOfFieldUsageCollection c = new EnumOfFieldUsageCollection(ce); + + SimplTypesScope t = SimplTypesScope.get("enumCollectionTest",EnumOfFieldUsageCollection.class); + SimplTypesScope.enableGraphSerialization(); + + TestingUtils.test(c, t, Format.XML); + TestingUtils.test(c, t, Format.JSON); + TestingUtils.test(c, t, Format.TLV); + + } + + +} diff --git a/simplTests/test/legacy/tests/scalar/NonsenseEnum.java b/simplTests/test/legacy/tests/scalar/NonsenseEnum.java index f72c5bd7..af4ca483 100644 --- a/simplTests/test/legacy/tests/scalar/NonsenseEnum.java +++ b/simplTests/test/legacy/tests/scalar/NonsenseEnum.java @@ -1,7 +1,7 @@ -package legacy.tests.scalar; - -public enum NonsenseEnum { - ONE, - TWO, - BUCKLE_MY_SHOES -} +package legacy.tests.scalar; + +public enum NonsenseEnum { + ONE, + TWO, + BUCKLE_MY_SHOES +} diff --git a/simplTests/test/legacy/tests/scalar/ScalarCollection.java b/simplTests/test/legacy/tests/scalar/ScalarCollection.java index ca8ddc80..93420c59 100644 --- a/simplTests/test/legacy/tests/scalar/ScalarCollection.java +++ b/simplTests/test/legacy/tests/scalar/ScalarCollection.java @@ -1,49 +1,69 @@ -package legacy.tests.scalar; - -import java.util.ArrayList; - -import legacy.tests.TestCase; -import legacy.tests.TestingUtils; - -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.formatenums.Format; - -public class ScalarCollection implements TestCase -{ - @simpl_nowrap - @simpl_collection("circles") - private ArrayList collectionOfIntegers; - - public ScalarCollection() - { - collectionOfIntegers = new ArrayList(); - } - - public void addInt(int integer) - { - collectionOfIntegers.add(integer); - } - - @Override - public void runTest() throws SIMPLTranslationException - { - ScalarCollection sc = new ScalarCollection(); - - sc.addInt(1); - sc.addInt(2); - sc.addInt(3); - sc.addInt(4); - sc.addInt(5); - - SimplTypesScope scalarCollectionTranslationScope = SimplTypesScope.get( - "scalarCollectionTScope", ScalarCollection.class); - - TestingUtils.test(sc, scalarCollectionTranslationScope, Format.XML); - - TestingUtils.test(sc, scalarCollectionTranslationScope, Format.JSON); - TestingUtils.test(sc, scalarCollectionTranslationScope, Format.TLV); - } -} \ No newline at end of file +package legacy.tests.scalar; + +import java.util.ArrayList; +import java.util.List; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.formatenums.Format; + +public class ScalarCollection implements TestCase +{ + @simpl_nowrap + @simpl_collection("circles") + private ArrayList collectionOfIntegers; + + @simpl_collection("location") + private List additionalLocations; + + public ScalarCollection() + { + collectionOfIntegers = new ArrayList(); + } + + public void addInt(int integer) + { + collectionOfIntegers.add(integer); + } + + public List getInts() + { + return collectionOfIntegers; + } + + @Override + public void runTest() throws SIMPLTranslationException + { + ScalarCollection sc = new ScalarCollection(); + + sc.addInt(1); + sc.addInt(2); + sc.addInt(3); + sc.addInt(4); + sc.addInt(5); + + SimplTypesScope scalarCollectionTranslationScope = SimplTypesScope.get( + "scalarCollectionTScope", ScalarCollection.class); + + TestingUtils.test(sc, scalarCollectionTranslationScope, Format.XML); + + TestingUtils.test(sc, scalarCollectionTranslationScope, Format.JSON); + TestingUtils.test(sc, scalarCollectionTranslationScope, Format.TLV); + } + + public List getAdditionalLocations() + { + return additionalLocations; + } + + public void setAdditionalLocations(List additionalLocations) + { + this.additionalLocations = additionalLocations; + } + +} diff --git a/simplTests/test/legacy/tests/test.xml b/simplTests/test/legacy/tests/test.xml index 0a2ab85c..29ebedc4 100644 --- a/simplTests/test/legacy/tests/test.xml +++ b/simplTests/test/legacy/tests/test.xml @@ -1,2693 +1,2693 @@ - - - - - - - - - - - - - - PES - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CITATION_SEMANTIC_ACTION - TRUSTED_SEMANTIC_ACTION - SITE_BOOSTED_SEMANTIC_ACTION - OTHER_SEMANTIC_ACTION - WILD_CONTENT_BODY - WILD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - regex_split - - - - - - - - - - - - - - - - - - - - - - - - - - - - field_name - described_class_name - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inerface - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - T - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - T - - - - - - - - - - - - - - T - - - - - - - - - - - - T - - - - - - - - - - - - - - - - - - - - - - - - - - - - - XML_ATTRIBUTE - XML_LEAF - XML_LEAF_CDATA - XML_TEXT - XML_TEXT_CDATA - UNDEFINED - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - XML_ATTRIBUTE - XML_LEAF - XML_LEAF_CDATA - XML_TEXT - XML_TEXT_CDATA - UNDEFINED - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - M - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - REDIRECT_USUAL - REDIRECT_FOLLOW_DONT_RESET_LOCATION - REDIRECT_FOLLOW_GET_NEW_MM - - - - - - - - - - - - - - - - - - - - - - - - - - GLOBAL - PACKAGE - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + PES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CITATION_SEMANTIC_ACTION + TRUSTED_SEMANTIC_ACTION + SITE_BOOSTED_SEMANTIC_ACTION + OTHER_SEMANTIC_ACTION + WILD_CONTENT_BODY + WILD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + regex_split + + + + + + + + + + + + + + + + + + + + + + + + + + + + field_name + described_class_name + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + inerface + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T + + + + + + + + + + + + + + T + + + + + + + + + + + + T + + + + + + + + + + + + + + + + + + + + + + + + + + + + + XML_ATTRIBUTE + XML_LEAF + XML_LEAF_CDATA + XML_TEXT + XML_TEXT_CDATA + UNDEFINED + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + XML_ATTRIBUTE + XML_LEAF + XML_LEAF_CDATA + XML_TEXT + XML_TEXT_CDATA + UNDEFINED + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + M + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + REDIRECT_USUAL + REDIRECT_FOLLOW_DONT_RESET_LOCATION + REDIRECT_FOLLOW_GET_NEW_MM + + + + + + + + + + + + + + + + + + + + + + + + + + GLOBAL + PACKAGE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/simplTests/test/simpl/serialization/Article.java b/simplTests/test/simpl/serialization/Article.java new file mode 100644 index 00000000..d0395116 --- /dev/null +++ b/simplTests/test/simpl/serialization/Article.java @@ -0,0 +1,34 @@ +package simpl.serialization; + + +import java.util.ArrayList; +import java.util.List; + + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +public class Article +{ + @simpl_scalar + String title; + + @simpl_collection("author") + List authors; + + + public Article(String t, List a) + { + title = t; + authors = a; + } + + public Article() + { + + } + +} diff --git a/simplTests/test/simpl/serialization/Author.java b/simplTests/test/simpl/serialization/Author.java new file mode 100644 index 00000000..3a88099a --- /dev/null +++ b/simplTests/test/simpl/serialization/Author.java @@ -0,0 +1,31 @@ +package simpl.serialization; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.simpl_composite_as_scalar; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + + +public class Author +{ + @simpl_composite_as_scalar + @simpl_scalar + String name; + + @simpl_scalar + String city; + + public Author(String n, String c) + { + name = n; + city = c; + } + + public Author() + { + + } + + +} diff --git a/simplTests/test/simpl/serialization/SimplBibtexDeSerializationTest.java b/simplTests/test/simpl/serialization/SimplBibtexDeSerializationTest.java new file mode 100644 index 00000000..825ae278 --- /dev/null +++ b/simplTests/test/simpl/serialization/SimplBibtexDeSerializationTest.java @@ -0,0 +1,72 @@ +package simpl.serialization; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.ArrayList; + +import org.junit.Test; + + +import legacy.tests.DualBufferOutputStream; +import legacy.tests.maps.ClassDes; +import legacy.tests.maps.FieldDes; +import legacy.tests.maps.TranslationS; +import ecologylab.generic.ReflectionTools; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; + +import static org.junit.Assert.*; + +public class SimplBibtexDeSerializationTest { + + @Test + public void bibtexDeSerializationTest() throws SIMPLTranslationException{ + + //NOTE: Bibtex is not implemented yet in SimplPullDeserializer, so this test is not useful, or complete, yet. + + Author a1 = new Author("Author One", "City"); + Author a2 = new Author("Author Two", "Place"); + + ArrayList authors = new ArrayList(); + authors.add(a1); + authors.add(a2); + + String title = "Article being serialized"; + + Article article = new Article(title, authors); + + Field[] articleFields = Article.class.getFields(); + + SimplTypesScope tScope = SimplTypesScope.get("bibtexTestScope", Article.class, Author.class); + + //BIBTEX=== + DualBufferOutputStream bibtexOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(article, bibtexOStream, Format.BIBTEX); + + String bibtexResult = bibtexOStream.toString(); + + assertEquals(bibtexResult, "@article{title={Article being serialized},authors={Author One,Author Two}}"); + + InputStream bibtexIStream = new ByteArrayInputStream(bibtexOStream.toByte()); + + Object bibtexObject = tScope.deserialize(bibtexIStream, Format.BIBTEX); + + //assertTrue(bibtexObject instanceof Article); + + //Article bibtexArticle = (Article) bibtexObject; + + //bibtexArticle.simplEquals()yadaa yadaa + + //for(Field i: articleFields){ + // assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(bibtexArticle, i), ReflectionTools.getFieldValue(article, i)); + + //} + + //Need assert Statements + + //=== + + } +} diff --git a/simplTests/test/simpl/serialization/SimplCompositeCollectionDeSerializationTest.java b/simplTests/test/simpl/serialization/SimplCompositeCollectionDeSerializationTest.java new file mode 100644 index 00000000..a47063ea --- /dev/null +++ b/simplTests/test/simpl/serialization/SimplCompositeCollectionDeSerializationTest.java @@ -0,0 +1,81 @@ +package simpl.serialization; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.lang.reflect.Field; + +import legacy.tests.DualBufferOutputStream; +import legacy.tests.circle.Circle; +import legacy.tests.circle.CollectionOfCircles; +import legacy.tests.circle.Point; + +import org.junit.Test; + +import ecologylab.generic.ReflectionTools; +import ecologylab.serialization.DeserializationHookStrategy; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; + +public class SimplCompositeCollectionDeSerializationTest { + + @Test + public void compositeCollectionDeSerializationTest() throws SIMPLTranslationException + { + CollectionOfCircles coc = new CollectionOfCircles(); + + coc.addCircle(1, 2, 3); + coc.addCircle(1, 2, 4); + coc.addCircle(1, 2, 5); + coc.addCircle(1, 2, 6); + coc.addCircle(1, 2, 7); + + SimplTypesScope circleTranslationScope = SimplTypesScope.get("collectionOfCirclesTScope", + CollectionOfCircles.class, Circle.class, Point.class); + + Field[] cocFields = CollectionOfCircles.class.getFields(); + + //JSON=== + DualBufferOutputStream jsonOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(coc, jsonOStream, Format.JSON); + + String jsonResult = jsonOStream.toString(); + + assertEquals("Serialized JSON string did not match expected", jsonResult, "{\"collection_of_circles\":{\"collection_of_circles\":{\"circles\":[{\"radius\":\"1\",\"center\":{\"x\":\"2\",\"y\":\"3\"}},{\"radius\":\"1\",\"center\":{\"x\":\"2\",\"y\":\"4\"}},{\"radius\":\"1\",\"center\":{\"x\":\"2\",\"y\":\"5\"}},{\"radius\":\"1\",\"center\":{\"x\":\"2\",\"y\":\"6\"}},{\"radius\":\"1\",\"center\":{\"x\":\"2\",\"y\":\"7\"}}]},\"yo\":\"1\"}}"); + + InputStream jsonIStream = new ByteArrayInputStream(jsonOStream.toByte()); + Object jsonObject = circleTranslationScope.deserialize(jsonIStream, (DeserializationHookStrategy) null, Format.JSON, null); + + assertTrue(jsonObject instanceof CollectionOfCircles); + CollectionOfCircles coc_json = (CollectionOfCircles) jsonObject; + + for(Field i:cocFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(coc_json, i), ReflectionTools.getFieldValue(coc, i)); + } + + //=== + + //XML=== + DualBufferOutputStream xmlOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(coc, xmlOStream, Format.XML); + + String xmlResult = xmlOStream.toString(); + + assertEquals("Serialized XML string did not match expected", xmlResult, "1

1
1
1
1
1"); + + InputStream xmlIStream = new ByteArrayInputStream(xmlOStream.toByte()); + Object xmlObject = circleTranslationScope.deserialize(xmlIStream, (DeserializationHookStrategy) null, Format.XML, null); + + assertTrue(xmlObject instanceof CollectionOfCircles); + CollectionOfCircles coc_xml = (CollectionOfCircles) xmlObject; + + for(Field i:cocFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(coc_xml, i), ReflectionTools.getFieldValue(coc, i)); + + } + + //=== + } +} diff --git a/simplTests/test/simpl/serialization/SimplCompositeDeSerializationTest.java b/simplTests/test/simpl/serialization/SimplCompositeDeSerializationTest.java new file mode 100644 index 00000000..7600b17e --- /dev/null +++ b/simplTests/test/simpl/serialization/SimplCompositeDeSerializationTest.java @@ -0,0 +1,81 @@ +package simpl.serialization; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; + +import legacy.tests.DualBufferOutputStream; +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import legacy.tests.circle.Circle; +import legacy.tests.circle.Point; + + +import ecologylab.generic.ReflectionTools; +import ecologylab.serialization.DeserializationHookStrategy; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.library.rest.Fields; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class SimplCompositeDeSerializationTest { + + @Test + public void compositeDeSerializationTest() throws SIMPLTranslationException + { + Point p = new Point(1, -1); + Circle c = new Circle(3, p); + SimplTypesScope s = SimplTypesScope.get("circlescope", Point.class, Circle.class); + SimplTypesScope.enableGraphSerialization(); + + Field[] circleFields = Circle.class.getFields(); + + //JSON=== + DualBufferOutputStream outputStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(c, outputStream, Format.JSON); + + String result = outputStream.toString(); + assertEquals("Serialized JSON string did not match expected", "{\"circle\":{\"radius\":\"3\",\"center\":{\"x\":\"1\",\"y\":\"-1\"}}}", result); + + InputStream inputStream = new ByteArrayInputStream(outputStream.toByte()); + + Object jsonObject = s.deserialize(inputStream, (DeserializationHookStrategy) null, Format.JSON, null); + assertTrue(jsonObject instanceof Circle); + Circle jsonCircle = (Circle) jsonObject; + + for(Field i: circleFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(jsonCircle, i), ReflectionTools.getFieldValue(c, i)); + } + + //=== + + //XML=== + DualBufferOutputStream xmlOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(c, xmlOStream, Format.XML); + + String xmlResult = xmlOStream.toString(); + assertEquals("Serialized XML string did not match expected", "3
", xmlResult); + + InputStream xmlIStream = new ByteArrayInputStream(xmlOStream.toByte()); + + Object xmlObject = s.deserialize(xmlIStream, (DeserializationHookStrategy) null, Format.XML, null); + assertTrue(xmlObject instanceof Circle); + Circle xmlCircle = (Circle) xmlObject; + + for(Field i: circleFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(xmlCircle, i), ReflectionTools.getFieldValue(c, i)); + } + + //=== + } +} \ No newline at end of file diff --git a/simplTests/test/simpl/serialization/SimplCompositeInheritanceDeSerializationTest.java b/simplTests/test/simpl/serialization/SimplCompositeInheritanceDeSerializationTest.java new file mode 100644 index 00000000..9679bfb6 --- /dev/null +++ b/simplTests/test/simpl/serialization/SimplCompositeInheritanceDeSerializationTest.java @@ -0,0 +1,78 @@ +package simpl.serialization; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.lang.reflect.Field; + +import legacy.tests.DualBufferOutputStream; +import legacy.tests.inheritance.BaseClass; +import legacy.tests.inheritance.ChildClass1; +import legacy.tests.inheritance.ChildClass2; +import legacy.tests.inheritance.ContainingClass; + +import org.junit.Test; + +import ecologylab.generic.ReflectionTools; +import ecologylab.serialization.DeserializationHookStrategy; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; + +public class SimplCompositeInheritanceDeSerializationTest { + + @Test + public void compositeInheritanceDeSerializationTest() throws SIMPLTranslationException{ + + SimplTypesScope translationScope = SimplTypesScope.get("containingClassTScope", ContainingClass.class, + BaseClass.class); + + ContainingClass ccb = new ContainingClass(); + ccb.setTheField(new BaseClass()); + + Field[] ccbFields = ContainingClass.class.getFields(); + + + //JSON=== + DualBufferOutputStream jsonOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(ccb, jsonOStream, Format.JSON); + + String jsonResult = jsonOStream.toString(); + assertEquals(jsonResult, "{\"containing_class\":{\"fred\":{\"new_tag_var\":\"3\"}}}"); + + InputStream jsonIStream = new ByteArrayInputStream(jsonOStream.toByte()); + + Object jsonObject =translationScope.deserialize(jsonIStream, (DeserializationHookStrategy) null, Format.JSON, null); + assertTrue(jsonObject instanceof ContainingClass); + ContainingClass jsonCCB = (ContainingClass) jsonObject; + + for(Field i:ccbFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(jsonCCB, i), ReflectionTools.getFieldValue(ccb, i)); + } + + + //=== + + //XML=== + DualBufferOutputStream xmlOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(ccb, xmlOStream, Format.XML); + + String xmlResult = xmlOStream.toString(); + assertEquals(xmlResult, ""); + + InputStream xmlIStream = new ByteArrayInputStream(xmlOStream.toByte()); + + Object xmlObject =translationScope.deserialize(xmlIStream, (DeserializationHookStrategy) null, Format.XML, null); + assertTrue(xmlObject instanceof ContainingClass); + ContainingClass xmlCCB = (ContainingClass) xmlObject; + + for(Field i:ccbFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(xmlCCB, i), ReflectionTools.getFieldValue(ccb, i)); + } + + + //=== + } +} diff --git a/simplTests/test/simpl/serialization/SimplGraphDeSerializationTest.java b/simplTests/test/simpl/serialization/SimplGraphDeSerializationTest.java new file mode 100644 index 00000000..fa082bec --- /dev/null +++ b/simplTests/test/simpl/serialization/SimplGraphDeSerializationTest.java @@ -0,0 +1,103 @@ +package simpl.serialization; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.lang.reflect.Field; + +import legacy.tests.DualBufferOutputStream; +import legacy.tests.graph.ClassA; +import legacy.tests.graph.ClassB; + + + +import org.junit.Test; + +import ecologylab.generic.ReflectionTools; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; + + +public class SimplGraphDeSerializationTest { + + @Test + public void graphDeSerializationTest() throws SIMPLTranslationException{ + + //NOTE: Currently, the only verification for correct serialization, is correct deserialization. + + + SimplTypesScope.enableGraphSerialization(); + + ClassA test = new ClassA(1, 2); + ClassB classB = new ClassB(3, 4, test); + + test.setClassB(classB); + + Field[] classAFields = ClassA.class.getFields(); + + SimplTypesScope translationScope = SimplTypesScope.get("classATScope", ClassA.class, ClassB.class); + + + //JSON=== + DualBufferOutputStream jsonOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(test, jsonOStream, Format.JSON); + + String jsonResult = jsonOStream.toString(); + + InputStream jsonIStream = new ByteArrayInputStream(jsonOStream.toByte()); + + + Object jsonObject = translationScope.deserialize(jsonIStream,Format.JSON); + + assertTrue(jsonObject instanceof ClassA); + + ClassA jsonClassA = (ClassA) jsonObject; + assertTrue(jsonClassA.getClassB() instanceof ClassB); + + assertEquals(jsonClassA.getX(), test.getX()); + assertEquals(jsonClassA.getY(), test.getY()); + assertEquals(jsonClassA.getClassB().getA(), test.getClassB().getA()); + assertEquals(jsonClassA.getClassB().getB(), test.getClassB().getB()); + + + for(Field i:classAFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(jsonClassA, i), ReflectionTools.getFieldValue(test, i)); + } + + + //=== + + + //XML=== + DualBufferOutputStream xmlOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(test, xmlOStream, Format.XML); + + String xmlResult = xmlOStream.toString(); + + InputStream xmlIStream = new ByteArrayInputStream(xmlOStream.toByte()); + + + Object xmlObject = translationScope.deserialize(xmlIStream,Format.XML); + + assertTrue(xmlObject instanceof ClassA); + + ClassA xmlClassA = (ClassA) xmlObject; + assertTrue(xmlClassA.getClassB() instanceof ClassB); + + assertEquals(xmlClassA.getX(), test.getX()); + assertEquals(xmlClassA.getY(), test.getY()); + assertEquals(xmlClassA.getClassB().getA(), test.getClassB().getA()); + assertEquals(xmlClassA.getClassB().getB(), test.getClassB().getB()); + + for(Field i:classAFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(xmlClassA, i), ReflectionTools.getFieldValue(test, i)); + } + + //=== + + SimplTypesScope.disableGraphSerialization(); + + } +} diff --git a/simplTests/test/simpl/serialization/SimplMapsDeSerializationTest.java b/simplTests/test/simpl/serialization/SimplMapsDeSerializationTest.java new file mode 100644 index 00000000..c982e956 --- /dev/null +++ b/simplTests/test/simpl/serialization/SimplMapsDeSerializationTest.java @@ -0,0 +1,96 @@ +package simpl.serialization; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.HashMap; + +import legacy.tests.DualBufferOutputStream; + +import legacy.tests.maps.ClassDes; +import legacy.tests.maps.FieldDes; +import legacy.tests.maps.TranslationS; + +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import ecologylab.generic.ReflectionTools; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; + +import org.junit.Test; + +public class SimplMapsDeSerializationTest { + + @Test + public void mapsDeSerializationTest() throws SIMPLTranslationException{ + + //Could not complete the test in time, SimplEquals, once implemented, may make this easier. + + TranslationS trans = new TranslationS(); + + ClassDes cd1 = new ClassDes("cd1"); + + cd1.fieldDescriptorsByTagName.put("fd1_cd1", new FieldDes("fd1_cd1")); + cd1.fieldDescriptorsByTagName.put("fd2_cd1", new FieldDes("fd2_cd1")); + cd1.fieldDescriptorsByTagName.put("fd3_cd1", new FieldDes("fd3_cd1")); + + ClassDes cd2 = new ClassDes("cd2"); + cd2.fieldDescriptorsByTagName.put("fd1_cd2", new FieldDes("fd1_cd2")); + cd2.fieldDescriptorsByTagName.put("fd2_cd2", new FieldDes("fd2_cd2")); + cd2.fieldDescriptorsByTagName.put("fd3_cd2", new FieldDes("fd3_cd2")); + + trans.entriesByTag.put("cd1", cd1); + trans.entriesByTag.put("cd2", cd2); + + SimplTypesScope tScope = SimplTypesScope.get("testingMapWithinMapsTScope", TranslationS.class, ClassDes.class, + FieldDes.class); + + SimplTypesScope.enableGraphSerialization(); + + Field[] translationSFields = TranslationS.class.getFields(); + + + //JSON=== + DualBufferOutputStream jsonOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(trans, jsonOStream, Format.JSON); + + String jsonResult = jsonOStream.toString(); + assertEquals(jsonResult, "{\"translation_s\":{\"class_descriptor\":[{\"tag_name\":\"cd1\",\"field_descriptor\":[{\"field_name\":\"fd3_cd1\"},{\"field_name\":\"fd2_cd1\"},{\"field_name\":\"fd1_cd1\"}]},{\"tag_name\":\"cd2\",\"field_descriptor\":[{\"field_name\":\"fd2_cd2\"},{\"field_name\":\"fd3_cd2\"},{\"field_name\":\"fd1_cd2\"}]}]}}"); + + InputStream jsonIStream = new ByteArrayInputStream(jsonOStream.toByte()); + + Object jsonObject = tScope.deserialize(jsonIStream, Format.JSON); + assertTrue(jsonObject instanceof TranslationS); + TranslationS jsonTranslationS = (TranslationS) jsonObject; + + //assertEquals(jsonTranslationS); + + /*for(Field i:translationSFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(jsonTranslationS, i), ReflectionTools.getFieldValue(trans, i)); + }*/ + + //=== + + //XML=== + DualBufferOutputStream xmlOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(trans, xmlOStream, Format.XML); + + String xmlResult = xmlOStream.toString(); + assertEquals(xmlResult, ""); + + InputStream xmlIStream = new ByteArrayInputStream(xmlOStream.toByte()); + + Object xmlObject = tScope.deserialize(xmlIStream, Format.XML); + assertTrue(xmlObject instanceof TranslationS); + TranslationS xmlTranslationS = (TranslationS) xmlObject; + + //for(int i = 0; i < xmlTranslationS.entriesByTag.size(); i++){ + // assertEquals(xmlTranslationS.entriesByTag.values().toArray()[i], trans.entriesByTag.values().toArray()[i]); + //} + + //assertEquals(xmlTranslationS); + } +} \ No newline at end of file diff --git a/simplTests/test/simpl/serialization/SimplMonomorphicCollectionDeSerializationTest.java b/simplTests/test/simpl/serialization/SimplMonomorphicCollectionDeSerializationTest.java new file mode 100644 index 00000000..4ae877bb --- /dev/null +++ b/simplTests/test/simpl/serialization/SimplMonomorphicCollectionDeSerializationTest.java @@ -0,0 +1,78 @@ +package simpl.serialization; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.lang.reflect.Field; + +import legacy.tests.DualBufferOutputStream; +import legacy.tests.inheritance.BaseClass; +import legacy.tests.inheritance.ContainingClass; +import legacy.tests.person.Faculty; +import legacy.tests.person.Person; +import legacy.tests.person.PersonDirectory; +import legacy.tests.person.Student; +import legacy.tests.person.StudentDirectory; + +import org.junit.Test; + +import ecologylab.generic.ReflectionTools; +import ecologylab.serialization.DeserializationHookStrategy; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; + +public class SimplMonomorphicCollectionDeSerializationTest { + + @Test + public void monomorphicCollectionDeSerializationTest() throws SIMPLTranslationException{ + + StudentDirectory sd = new StudentDirectory(); + sd.initializeDirectory(); + + Field[] sdFields = StudentDirectory.class.getFields(); + + SimplTypesScope translationScope = SimplTypesScope.get("studentDirectoryTScope", Person.class, + Faculty.class, Student.class, StudentDirectory.class); + + + //JSON=== + DualBufferOutputStream jsonOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(sd, jsonOStream, Format.JSON); + + String jsonResult = jsonOStream.toString(); + assertEquals(jsonResult, "{\"student_directory\":{\"student\":[{\"name\":\"nabeel\",\"stu_num\":\"234342\"},{\"name\":\"yin\",\"stu_num\":\"423423\"},{\"name\":\"bill\",\"stu_num\":\"4234234\"},{\"name\":\"sashi\",\"stu_num\":\"5454\"},{\"name\":\"jon\",\"stu_num\":\"656565\"}],\"test\":\"nabel\"}}"); + + InputStream jsonIStream = new ByteArrayInputStream(jsonOStream.toByte()); + + Object jsonObject = translationScope.deserialize(jsonIStream,Format.JSON); + assertTrue(jsonObject instanceof StudentDirectory); + StudentDirectory jsonDirectory = (StudentDirectory) jsonObject; + + for(Field i:sdFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(jsonDirectory, i), ReflectionTools.getFieldValue(sd, i)); + } + + //=== + + //XML=== + DualBufferOutputStream xmlOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(sd, xmlOStream, Format.XML); + + String xmlResult = xmlOStream.toString(); + assertEquals(xmlResult, "nabel"); + + InputStream xmlIStream = new ByteArrayInputStream(xmlOStream.toByte()); + + Object xmlObject = translationScope.deserialize(xmlIStream, (DeserializationHookStrategy) null, Format.XML); + assertTrue(xmlObject instanceof StudentDirectory); + StudentDirectory xmlDirectory = (StudentDirectory) xmlObject; + + for(Field i:sdFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(xmlDirectory, i), ReflectionTools.getFieldValue(sd, i)); + } + + //=== + } +} diff --git a/simplTests/test/simpl/serialization/SimplPolymorphicCollectionDeSerializationTest.java b/simplTests/test/simpl/serialization/SimplPolymorphicCollectionDeSerializationTest.java new file mode 100644 index 00000000..1aa00d76 --- /dev/null +++ b/simplTests/test/simpl/serialization/SimplPolymorphicCollectionDeSerializationTest.java @@ -0,0 +1,75 @@ +package simpl.serialization; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.lang.reflect.Field; + +import legacy.tests.DualBufferOutputStream; +import legacy.tests.inheritance.BaseClass; +import legacy.tests.inheritance.ContainingClass; +import legacy.tests.person.Faculty; +import legacy.tests.person.Person; +import legacy.tests.person.PersonDirectory; +import legacy.tests.person.Student; +import legacy.tests.person.StudentDirectory; + +import org.junit.Test; + +import ecologylab.generic.ReflectionTools; +import ecologylab.serialization.DeserializationHookStrategy; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.Format; + +public class SimplPolymorphicCollectionDeSerializationTest { + + @Test + public void polymorphicCollectionDeSerializationTest() throws SIMPLTranslationException{ + + PersonDirectory pd = new PersonDirectory(); + pd.initializeDirectory(); + + SimplTypesScope translationScope = SimplTypesScope.get("personDirectoryTScope", Person.class,Faculty.class, Student.class, PersonDirectory.class); + + Field[] pdFields = PersonDirectory.class.getFields(); + + + //JSON=== + DualBufferOutputStream jsonOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(pd, jsonOStream, Format.JSON); + + String jsonResult = jsonOStream.toString(); + assertEquals(jsonResult, "{\"person_directory\":{\"persons\":[{\"student\":{\"name\":\"nabeel\",\"stu_num\":\"234342\"}},{\"student\":{\"name\":\"yin\",\"stu_num\":\"423423\"}},{\"faculty\":{\"name\":\"andruid\",\"designation\":\"prof\"}},{\"student\":{\"name\":\"bill\",\"stu_num\":\"4234234\"}},{\"student\":{\"name\":\"sashi\",\"stu_num\":\"5454\"}},{\"student\":{\"name\":\"jon\",\"stu_num\":\"656565\"}}]}}"); + + InputStream jsonIStream = new ByteArrayInputStream(jsonOStream.toByte()); + + Object jsonObject = translationScope.deserialize(jsonIStream,Format.JSON); + assertTrue(jsonObject instanceof PersonDirectory); + PersonDirectory jsonPD = (PersonDirectory) jsonObject; + + for(Field i:pdFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(jsonPD, i), ReflectionTools.getFieldValue(pd, i)); + } + //=== + + //XML=== + DualBufferOutputStream xmlOStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(pd, xmlOStream, Format.XML); + + String xmlResult = xmlOStream.toString(); + assertEquals(xmlResult, ""); + + InputStream xmlIStream = new ByteArrayInputStream(xmlOStream.toByte()); + + Object xmlObject = translationScope.deserialize(xmlIStream,Format.XML); + assertTrue(xmlObject instanceof PersonDirectory); + PersonDirectory xmlPD = (PersonDirectory) xmlObject; + + for(Field i:pdFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(xmlPD, i), ReflectionTools.getFieldValue(pd, i)); + } + //=== + } +} diff --git a/simplTests/test/simpl/serialization/SimplScalarCollectionDeSerializationTest.java b/simplTests/test/simpl/serialization/SimplScalarCollectionDeSerializationTest.java new file mode 100644 index 00000000..0b640a7a --- /dev/null +++ b/simplTests/test/simpl/serialization/SimplScalarCollectionDeSerializationTest.java @@ -0,0 +1,79 @@ +package simpl.serialization; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import legacy.tests.scalar.ScalarCollection; + +import org.junit.Test; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.StringFormat; + +public class SimplScalarCollectionDeSerializationTest { + + @Test + public void scalarCollectionDeSerializationTest() throws SIMPLTranslationException + { + SimplTypesScope.enableGraphSerialization(); + + ScalarCollection sc = new ScalarCollection(); + sc.addInt(1); + sc.addInt(2); + sc.addInt(3); + sc.addInt(4); + sc.addInt(5); + + SimplTypesScope translationScope = SimplTypesScope.get("scalarCollectionTScope", ScalarCollection.class); + + + //JSON=== + String json = SimplTypesScope.serialize(sc, StringFormat.JSON).toString(); + System.out.println(json); + assertEquals(json, "{\"scalar_collection\":{\"collection_of_integers\":[\"1\",\"2\",\"3\",\"4\",\"5\"]}}"); + + ScalarCollection sc1 = (ScalarCollection) translationScope.deserialize(json, StringFormat.JSON); + assertEquals(5, sc1.getInts().size()); + for (int i = 0; i < 5; ++i) + { + assertEquals(i + 1, (int)sc1.getInts().get(i)); + } + //=== + + + //XML=== + String xml = SimplTypesScope.serialize(sc, StringFormat.XML).toString(); + System.out.println(json); + assertEquals(xml, "12345"); + + ScalarCollection sc2 = (ScalarCollection) translationScope.deserialize(xml, StringFormat.XML); + assertEquals(5, sc2.getInts().size()); + for (int i = 0; i < 5; ++i) + { + assertEquals(i + 1, (int)sc2.getInts().get(i)); + } + //=== + } + + @Test + public void scalarCollectionsInJsonAlwaysWrapped() throws SIMPLTranslationException + { + ScalarCollection sc = new ScalarCollection(); + List additionalLocations = new ArrayList(); + additionalLocations.add(ParsedURL.getAbsolute("http://example.com/page1")); + additionalLocations.add(ParsedURL.getAbsolute("http://example.com/page2")); + sc.setAdditionalLocations(additionalLocations); + + String json = SimplTypesScope.serialize(sc, StringFormat.JSON).toString(); + System.out.println(json); + assertTrue(json.contains("\"additional_locations\":[")); + assertFalse(json.contains("\"locations\":[")); + } + +} diff --git a/simplTests/test/simpl/serialization/SimplScalarDeSerializationTest.java b/simplTests/test/simpl/serialization/SimplScalarDeSerializationTest.java new file mode 100644 index 00000000..c053db3e --- /dev/null +++ b/simplTests/test/simpl/serialization/SimplScalarDeSerializationTest.java @@ -0,0 +1,89 @@ +package simpl.serialization; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import legacy.tests.DualBufferOutputStream; +import legacy.tests.TestCase; +import legacy.tests.TestingUtils; +import legacy.tests.circle.Point; + + +import ecologylab.serialization.DeserializationHookStrategy; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.Format; + +import static org.junit.Assert.*; + +import org.junit.Test; +import ecologylab.generic.*; +import java.lang.reflect.*; + +public class SimplScalarDeSerializationTest{ + + @Test + public void scalarDeSerializationTest() throws SIMPLTranslationException, IOException + { + + Point p = new Point(1,-1); + SimplTypesScope s = SimplTypesScope.get("pointscope", Point.class); + SimplTypesScope.enableGraphSerialization(); + Field[] pointFields = Point.class.getFields(); + + + //JSON=== + + DualBufferOutputStream jsonOPStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(p, jsonOPStream, Format.JSON); + + String result1 = jsonOPStream.toString(); + assertEquals(result1, "{\"point\":{\"x\":\"1\",\"y\":\"-1\"}}"); + + InputStream jsonIPStream = new ByteArrayInputStream(jsonOPStream.toByte()); + + Object o1 = s.deserialize(jsonIPStream, (DeserializationHookStrategy) null, Format.JSON, null); + assertTrue(o1 instanceof Point); + Point p1 = (Point) o1; + + for(Field i: pointFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(p1, i), ReflectionTools.getFieldValue(p, i)); + } + //=== + + + + //XML=== + DualBufferOutputStream xmlOPStream = new DualBufferOutputStream(); + SimplTypesScope.serialize(p,xmlOPStream, Format.XML); + + String result2 = xmlOPStream.toString(); + assertEquals(result2,"" ); + + InputStream xmlIPStream = new ByteArrayInputStream(xmlOPStream.toByte()); + + Object o2 = s.deserialize(xmlIPStream, (DeserializationHookStrategy) null, Format.XML, null); + assertTrue(o2 instanceof Point); + Point p2 = (Point) o2; + + for(Field i: pointFields){ + assertEquals("Field" + i.getName() + " did not deserialize correctly", ReflectionTools.getFieldValue(p2, i), ReflectionTools.getFieldValue(p, i)); + } + + //=== + + + + + + + + + } +} \ No newline at end of file diff --git a/simplTests/test/simpl/serialization/SimplSupplementaryCharacterTest.java b/simplTests/test/simpl/serialization/SimplSupplementaryCharacterTest.java new file mode 100644 index 00000000..3f2d08a9 --- /dev/null +++ b/simplTests/test/simpl/serialization/SimplSupplementaryCharacterTest.java @@ -0,0 +1,28 @@ +package simpl.serialization; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.StringFormat; + +public class SimplSupplementaryCharacterTest +{ + + @Test + public void testSupplementaryCharacter() throws SIMPLTranslationException + { + Article article = new Article(); + article.title = "\uD800\uDF40 and \uD803\uDC22"; + + String xml = SimplTypesScope.serialize(article, StringFormat.XML).toString(); + System.out.println(xml); + + SimplTypesScope tscope = SimplTypesScope.get("test-supplementary-chars", Article.class); + Article a1 = (Article) tscope.deserialize(xml, StringFormat.XML); + assertEquals(article.title, a1.title); + } + +} diff --git a/simplTests/test/simpl/translation/api/SourceAppenderTest.java b/simplTests/test/simpl/translation/api/SourceAppenderTest.java index ce7b022a..cb839113 100644 --- a/simplTests/test/simpl/translation/api/SourceAppenderTest.java +++ b/simplTests/test/simpl/translation/api/SourceAppenderTest.java @@ -1,59 +1,59 @@ -package simpl.translation.api; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import simpl.translation.api.SourceAppender; -import simpl.translation.api.SourceAppenderConfiguration; -import simpl.translation.api.SourceCodeAppender; -import simpl.translation.api.SourceEntry; - -public class SourceAppenderTest { - - @Test - public void test() { - - SourceAppenderConfiguration sac = new SourceAppenderConfiguration("\t", "\r\n", "{","}"); - SourceCodeAppender sca = new SourceCodeAppender(); - sca.append("package"); - sca.append(SourceEntry.BLOCK_BEGIN); - sca.append("inside"); - sca.append(SourceEntry.BLOCK_BEGIN); - sca.append("deeper"); - sca.append(SourceEntry.BLOCK_END); - sca.append(SourceEntry.BLOCK_END); - sca.append("after"); - - String result = sca.toSource(); - - assertEquals("package\r\n{\r\n\tinside\r\n\t{\r\n\t\tdeeper\r\n\t}\r\n}\r\nafter\r\n", result); - } - - @Test - public void testAppending() - { - SourceAppender sca = new SourceCodeAppender(); - assertEquals(0, sca.size()); - sca.append("a"); - assertEquals(1, sca.size()); - sca.append(SourceEntry.BREAK); - assertEquals(2, sca.size()); - - SourceAppender sca2 = new SourceCodeAppender().append("1"); - assertEquals(1, sca2.size()); - sca2.append("2").append("3"); - - assertEquals(3, sca2.size()); - - sca.append(sca2); - - assertEquals(5, sca.size()); - assertEquals(3, sca2.size()); - - sca2.append("4"); - assertEquals(5, sca.size()); - assertEquals(4, sca2.size()); - } - -} +package simpl.translation.api; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import simpl.translation.api.SourceAppender; +import simpl.translation.api.SourceAppenderConfiguration; +import simpl.translation.api.SourceCodeAppender; +import simpl.translation.api.SourceEntry; + +public class SourceAppenderTest { + + @Test + public void test() { + + SourceAppenderConfiguration sac = new SourceAppenderConfiguration("\t", "\r\n", "{","}"); + SourceCodeAppender sca = new SourceCodeAppender(); + sca.append("package"); + sca.append(SourceEntry.BLOCK_BEGIN); + sca.append("inside"); + sca.append(SourceEntry.BLOCK_BEGIN); + sca.append("deeper"); + sca.append(SourceEntry.BLOCK_END); + sca.append(SourceEntry.BLOCK_END); + sca.append("after"); + + String result = sca.toSource(); + + assertEquals("package\r\n{\r\n\tinside\r\n\t{\r\n\t\tdeeper\r\n\t}\r\n}\r\nafter\r\n", result); + } + + @Test + public void testAppending() + { + SourceAppender sca = new SourceCodeAppender(); + assertEquals(0, sca.size()); + sca.append("a"); + assertEquals(1, sca.size()); + sca.append(SourceEntry.BREAK); + assertEquals(2, sca.size()); + + SourceAppender sca2 = new SourceCodeAppender().append("1"); + assertEquals(1, sca2.size()); + sca2.append("2").append("3"); + + assertEquals(3, sca2.size()); + + sca.append(sca2); + + assertEquals(5, sca.size()); + assertEquals(3, sca2.size()); + + sca2.append("4"); + assertEquals(5, sca.size()); + assertEquals(4, sca2.size()); + } + +} diff --git a/simplTests/test/simpl/translators/java/JavaBasicScalarTranslationTest.java b/simplTests/test/simpl/translators/java/JavaBasicScalarTranslationTest.java index c52cd4bf..3dfc9b13 100644 --- a/simplTests/test/simpl/translators/java/JavaBasicScalarTranslationTest.java +++ b/simplTests/test/simpl/translators/java/JavaBasicScalarTranslationTest.java @@ -1,29 +1,29 @@ -package simpl.translators.java; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import simpl.tutorials.java.Book; - -import ecologylab.serialization.ClassDescriptor; - -public class JavaBasicScalarTranslationTest { - - @Test - public void testJavaBasicScalar() { - // Get the class descriptor for our test class: - ClassDescriptor bookDescriptor = ClassDescriptor.getClassDescriptor(Book.class); - - // Generate the source code - - JavaCompilationUnitTranslator translator = new JavaCompilationUnitTranslator(); - - String result = translator.translateClass(bookDescriptor); - - // This doesn't really validate anything; - // But, it does show you what the output would be! - System.out.println(result); - } - -} +package simpl.translators.java; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import simpl.tutorials.java.Book; + +import ecologylab.serialization.ClassDescriptor; + +public class JavaBasicScalarTranslationTest { + + @Test + public void testJavaBasicScalar() { + // Get the class descriptor for our test class: + ClassDescriptor bookDescriptor = ClassDescriptor.getClassDescriptor(Book.class); + + // Generate the source code + + JavaCompilationUnitTranslator translator = new JavaCompilationUnitTranslator(); + + String result = translator.translateClass(bookDescriptor); + + // This doesn't really validate anything; + // But, it does show you what the output would be! + System.out.println(result); + } + +} diff --git a/simplTests/test/simpl/tutorials/java/Book.java b/simplTests/test/simpl/tutorials/java/Book.java index 2373a379..29673f9d 100644 --- a/simplTests/test/simpl/tutorials/java/Book.java +++ b/simplTests/test/simpl/tutorials/java/Book.java @@ -1,52 +1,52 @@ -package simpl.tutorials.java; - -import ecologylab.serialization.annotations.simpl_other_tags; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.annotations.simpl_tag; - -public class Book { - - @simpl_scalar - String title; - - @simpl_scalar - String authorName; - - @simpl_scalar - @simpl_tag("book_number") - Integer bookId; - - public Book() - { - } - - public String getTitle() - { - return this.title; - } - - public void setTitle(String value) - { - this.title = value; - } - - public String getAuthorName() - { - return this.authorName; - } - - public void setAuthorName(String value) - { - this.authorName = value; - } - - public Integer getBookId() - { - return this.bookId; - } - - public void setBookId(Integer value) - { - this.bookId = value; - } -} +package simpl.tutorials.java; + +import ecologylab.serialization.annotations.simpl_other_tags; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.annotations.simpl_tag; + +public class Book { + + @simpl_scalar + String title; + + @simpl_scalar + String authorName; + + @simpl_scalar + @simpl_tag("book_number") + Integer bookId; + + public Book() + { + } + + public String getTitle() + { + return this.title; + } + + public void setTitle(String value) + { + this.title = value; + } + + public String getAuthorName() + { + return this.authorName; + } + + public void setAuthorName(String value) + { + this.authorName = value; + } + + public Integer getBookId() + { + return this.bookId; + } + + public void setBookId(Integer value) + { + this.bookId = value; + } +} diff --git a/simplTests/test/simpl/tutorials/java/serializeBookDescriptor.java b/simplTests/test/simpl/tutorials/java/serializeBookDescriptor.java index e9f39527..a06e847a 100644 --- a/simplTests/test/simpl/tutorials/java/serializeBookDescriptor.java +++ b/simplTests/test/simpl/tutorials/java/serializeBookDescriptor.java @@ -1,87 +1,87 @@ -package simpl.tutorials.java; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.TranslationContext; -import ecologylab.serialization.annotations.simpl_other_tags; -import ecologylab.serialization.formatenums.Format; -import ecologylab.serialization.formatenums.StringFormat; - -public class serializeBookDescriptor { - - @Test - public void serializeABook() throws SIMPLTranslationException { - - Book abook = new Book(); - // Here's an instance of our type to serialize. - - abook.setAuthorName("Michael Feathers"); - abook.setBookId(1337); - abook.setTitle("Working Effectively with Legacy Code"); - // S.IM.PL serialized objects don't have to be JavaBeans; - // They can just be POJO's too! - - // Serialize to JSON - String jsonResult = SimplTypesScope.serialize(abook, StringFormat.JSON).toString(); - System.out.println(jsonResult); // Print out the result - - // Serialize to XML - // (Just change the StringFormat parameter!) - String xmlResult = SimplTypesScope.serialize(abook, StringFormat.XML).toString(); - System.out.println(xmlResult); // Print out the result - } - - @Test - public void deserializeABook() throws SIMPLTranslationException - { - // S.IM.PL Deserialization is guided by the information contained - // within the "Simpl Types Scope" - // To deserialize, we need to either - // 1: Load a STS from a file - // 2: Construct our own STS. - // (For "Target Languages" which don't have vivid type information - // Python, etc... 1 is your only option) - - // A STS should contain all of the classes we expect to encounter - // Here, we're just expecting books! - SimplTypesScope book_example_sts = SimplTypesScope.get("book_example", Book.class); - // This STS is called "book_example"; when you have multiple named scopes, - // you can use those scopes for polymorphic type support... - // But more on that later. - - - String jsonBook = "{\"book\":{\"title\":\"Working Effectively with Legacy Code\",\"author_name\":\"Michael Feathers\",\"book_number\":\"1337\"}}"; - - Object result = book_example_sts.deserialize(jsonBook, new TranslationContext(), StringFormat.JSON); - - // We get back a book - assertTrue(result instanceof Book); - Book book_from_json = (Book)result; - - // Validate that our book is what we expected... - assertEquals("Michael Feathers", book_from_json.getAuthorName()); - assertEquals("Working Effectively with Legacy Code", book_from_json.getTitle()); - assertTrue(1337 == book_from_json.getBookId()); - // (It should be! S.IM.PL should just simply work!) - - // Same process applies for XML or other formats... - String xmlBook = ""; - - Object xml_result = book_example_sts.deserialize(xmlBook, new TranslationContext(), StringFormat.XML); - - // We get back a book - assertTrue(xml_result instanceof Book); - Book book_from_xml = (Book)result; - - // Validate that our book is what we expected... - assertEquals("Michael Feathers", book_from_xml.getAuthorName()); - assertEquals("Working Effectively with Legacy Code", book_from_xml.getTitle()); - assertTrue(1337 == book_from_xml.getBookId()); - // (It should be! S.IM.PL should just simply work!) - } -} +package simpl.tutorials.java; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.TranslationContext; +import ecologylab.serialization.annotations.simpl_other_tags; +import ecologylab.serialization.formatenums.Format; +import ecologylab.serialization.formatenums.StringFormat; + +public class serializeBookDescriptor { + + @Test + public void serializeABook() throws SIMPLTranslationException { + + Book abook = new Book(); + // Here's an instance of our type to serialize. + + abook.setAuthorName("Michael Feathers"); + abook.setBookId(1337); + abook.setTitle("Working Effectively with Legacy Code"); + // S.IM.PL serialized objects don't have to be JavaBeans; + // They can just be POJO's too! + + // Serialize to JSON + String jsonResult = SimplTypesScope.serialize(abook, StringFormat.JSON).toString(); + System.out.println(jsonResult); // Print out the result + + // Serialize to XML + // (Just change the StringFormat parameter!) + String xmlResult = SimplTypesScope.serialize(abook, StringFormat.XML).toString(); + System.out.println(xmlResult); // Print out the result + } + + @Test + public void deserializeABook() throws SIMPLTranslationException + { + // S.IM.PL Deserialization is guided by the information contained + // within the "Simpl Types Scope" + // To deserialize, we need to either + // 1: Load a STS from a file + // 2: Construct our own STS. + // (For "Target Languages" which don't have vivid type information + // Python, etc... 1 is your only option) + + // A STS should contain all of the classes we expect to encounter + // Here, we're just expecting books! + SimplTypesScope book_example_sts = SimplTypesScope.get("book_example", Book.class); + // This STS is called "book_example"; when you have multiple named scopes, + // you can use those scopes for polymorphic type support... + // But more on that later. + + + String jsonBook = "{\"book\":{\"title\":\"Working Effectively with Legacy Code\",\"author_name\":\"Michael Feathers\",\"book_number\":\"1337\"}}"; + + Object result = book_example_sts.deserialize(jsonBook, new TranslationContext(), StringFormat.JSON); + + // We get back a book + assertTrue(result instanceof Book); + Book book_from_json = (Book)result; + + // Validate that our book is what we expected... + assertEquals("Michael Feathers", book_from_json.getAuthorName()); + assertEquals("Working Effectively with Legacy Code", book_from_json.getTitle()); + assertTrue(1337 == book_from_json.getBookId()); + // (It should be! S.IM.PL should just simply work!) + + // Same process applies for XML or other formats... + String xmlBook = ""; + + Object xml_result = book_example_sts.deserialize(xmlBook, new TranslationContext(), StringFormat.XML); + + // We get back a book + assertTrue(xml_result instanceof Book); + Book book_from_xml = (Book)result; + + // Validate that our book is what we expected... + assertEquals("Michael Feathers", book_from_xml.getAuthorName()); + assertEquals("Working Effectively with Legacy Code", book_from_xml.getTitle()); + assertTrue(1337 == book_from_xml.getBookId()); + // (It should be! S.IM.PL should just simply work!) + } +} diff --git a/simplTests/unused/ecologylab/simpl/ConstructClassDescriptor.java b/simplTests/unused/ecologylab/simpl/ConstructClassDescriptor.java new file mode 100644 index 00000000..e0b58bee --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/ConstructClassDescriptor.java @@ -0,0 +1,212 @@ +package ecologylab.simpl; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.types.scalar.BooleanType; +import ecologylab.serialization.types.scalar.ByteType; +import ecologylab.serialization.types.scalar.CharType; +import ecologylab.serialization.types.scalar.DateType; +import ecologylab.serialization.types.scalar.DoubleType; +import ecologylab.serialization.FieldType; +import ecologylab.serialization.types.scalar.FloatType; +import ecologylab.serialization.types.scalar.IntType; +import ecologylab.serialization.types.scalar.LongType; +import ecologylab.serialization.types.scalar.ParsedURLType; +import ecologylab.serialization.types.scalar.PatternType; +import ecologylab.serialization.types.scalar.ReferenceBooleanType; +import ecologylab.serialization.types.scalar.ReferenceDoubleType; +import ecologylab.serialization.types.scalar.ReferenceFloatType; +import ecologylab.serialization.types.scalar.ReferenceIntegerType; +import ecologylab.serialization.types.scalar.ReferenceLongType; +import ecologylab.serialization.types.scalar.ShortType; +import ecologylab.serialization.types.scalar.StringBuilderType; +import ecologylab.serialization.types.scalar.StringType; +import ecologylab.serialization.types.scalar.URLType; +import ecologylab.serialization.types.scalar.UUIDType; +import ecologylab.simpl.simplescalar.SimpleBoolean; +import ecologylab.simpl.simplescalar.SimpleByte; +import ecologylab.simpl.simplescalar.SimpleChar; +import ecologylab.simpl.simplescalar.SimpleDate; +import ecologylab.simpl.simplescalar.SimpleDouble; +import ecologylab.simpl.simplescalar.SimpleFloat; +import ecologylab.simpl.simplescalar.SimpleInteger; +import ecologylab.simpl.simplescalar.SimpleJavaURL; +import ecologylab.simpl.simplescalar.SimpleLong; +import ecologylab.simpl.simplescalar.SimpleParsedURL; +import ecologylab.simpl.simplescalar.SimplePattern; +import ecologylab.simpl.simplescalar.SimpleShort; +import ecologylab.simpl.simplescalar.SimpleString; +import ecologylab.simpl.simplescalar.SimpleStringBuilder; +import ecologylab.simpl.simplescalar.SimpleUUID; +import ecologylab.simpl.simplescalar.Simpleprimboolean; +import ecologylab.simpl.simplescalar.Simpleprimbyte; +import ecologylab.simpl.simplescalar.Simpleprimchar; +import ecologylab.simpl.simplescalar.Simpleprimdouble; +import ecologylab.simpl.simplescalar.Simpleprimfloat; +import ecologylab.simpl.simplescalar.Simpleprimint; +import ecologylab.simpl.simplescalar.Simpleprimlong; +import ecologylab.simpl.simplescalar.Simpleprimshort; + +public class ConstructClassDescriptor { + + + // Todo: Stealthily swap this with a factory method. + private ClassDescriptor ConstructClassDescriptor(Class lass) + { + return ClassDescriptor.getClassDescriptor(lass); + } + + private void testSimpleScalar(Class lass, Class expectedType) + { + ClassDescriptor cd = ConstructClassDescriptor(lass); + + // Get the one field that is in the simple scalar class + assertEquals(1, cd.allFieldDescriptors().size()); + FieldDescriptor fd = cd.allFieldDescriptors().get(0); + assertEquals(lass.getSimpleName().toLowerCase(), fd.getName()); + assertEquals(FieldType.SCALAR, fd.getType()); + // TODO: BUG. //assertEquals(1, fd.getMetaInformation().size()); + assertEquals(expectedType, fd.getScalarType().getClass()); + + // TODO: Roundtrip the class descriptor. + + } + + // TODO: Roundtrip some range of values + + @Test + public void forSimpleBoolean() { + testSimpleScalar(SimpleBoolean.class, ReferenceBooleanType.class); + } + + @Test + public void forSimpleByte() { + testSimpleScalar(SimpleByte.class, ByteType.class); + } + + @Test + public void forSimpleChar(){ + testSimpleScalar(SimpleChar.class, CharType.class); + } + + @Test + public void forSimpleDate(){ + testSimpleScalar(SimpleDate.class, DateType.class); + } + + @Test + public void forSimpleDouble(){ + testSimpleScalar(SimpleDouble.class, ReferenceDoubleType.class); + } + + @Test + public void forSimpleFloat(){ + testSimpleScalar(SimpleFloat.class, ReferenceFloatType.class); + } + + @Test + public void forSimpleInteger() + { + testSimpleScalar(SimpleInteger.class, ReferenceIntegerType.class); + } + + @Test + public void forSimpleJavaURL(){ + testSimpleScalar(SimpleJavaURL.class, URLType.class); + } + + @Test + public void forSimpleLong(){ + testSimpleScalar(SimpleLong.class, ReferenceLongType.class); + } + + @Test + public void forSimpleParsedURL() + { + testSimpleScalar(SimpleParsedURL.class, ParsedURLType.class); + } + + @Test + public void forSimplePattern() + { + testSimpleScalar(SimplePattern.class, PatternType.class); + } + + @Test + public void forSimplePrimBoolean() + { + testSimpleScalar(Simpleprimboolean.class, BooleanType.class); + } + + @Test + public void forSimplePrimByte() + { + testSimpleScalar(Simpleprimbyte.class, ByteType.class); + } + + @Test + public void forSimplePrimChar() + { + testSimpleScalar(Simpleprimchar.class, CharType.class); + } + + @Test + public void forSimplePrimDouble() + { + testSimpleScalar(Simpleprimdouble.class, DoubleType.class); + } + + @Test + public void forSimplePrimFloat() + { + testSimpleScalar(Simpleprimfloat.class, FloatType.class); + } + + @Test + public void forSimplePrimInt() + { + testSimpleScalar(Simpleprimint.class, IntType.class); + } + + @Test + public void forSimplePrimLong() + { + testSimpleScalar(Simpleprimlong.class, LongType.class); + } + + @Test + public void forSimplePrimShort() + { + testSimpleScalar(Simpleprimshort.class, ShortType.class); + } + + // TODO. + @Test + public void forSimpleShort() + { + testSimpleScalar(SimpleShort.class, null); + } + + @Test + public void forSimpleString() + { + testSimpleScalar(SimpleString.class, StringType.class); + } + + @Test + public void forSimpleStringBuilder() + { + testSimpleScalar(SimpleStringBuilder.class, StringBuilderType.class); + } + + @Test + public void forSimpleUUID() + { + testSimpleScalar(SimpleUUID.class, UUIDType.class); + } + +} diff --git a/simplTests/unused/ecologylab/simpl/CreateSimpleScalars.java b/simplTests/unused/ecologylab/simpl/CreateSimpleScalars.java new file mode 100644 index 00000000..933d21b5 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/CreateSimpleScalars.java @@ -0,0 +1,100 @@ +package ecologylab.simpl; + +import java.io.File; +import java.io.IOException; +import com.google.common.io.Files; +import com.google.common.base.Charsets; + +public class CreateSimpleScalars { + + + static String getRepr(String name, String type, String include) + { + StringBuilder sb = new StringBuilder(); + + sb.append("package ecologylab.fundamental.simplescalar;\r\n"); + + if(!include.isEmpty()){ + sb.append("import "); + sb.append(include); + sb.append(";\r\n"); + } + + sb.append("import ecologylab.serialization.annotations.simpl_scalar;\r\n"); + sb.append(String.format("public class Simple%s {\r\n", name)); + sb.append("\t@simpl_scalar\r\n"); + sb.append(String.format("\tprivate %s simple%s;\r\n", type, name.toLowerCase())); + sb.append(String.format("\r\n\tpublic %s getSimple%s(){ \r\n", type, name)); + sb.append(String.format("\t\t return this.simple%s;\r\n", name.toLowerCase())); + sb.append("\t}\r\n"); + sb.append(String.format("\r\n\tpublic void setSimple%s(%s value){\r\n", name, type)); + sb.append(String.format("\t\tthis.simple%s = value;\r\n", name.toLowerCase())); + sb.append("\t}\r\n"); + sb.append("}\r\n"); + + return sb.toString(); + } + + + static File getFor(String name) throws IOException + { + File f = new File("C:\\Users\\tomwhite\\Documents\\test\\Simple" + name + ".java"); + f.createNewFile(); + return f; + } + + static void Create(String name, String type, String include) throws IOException + { + File f = getFor(name); + + Files.write(getRepr(name, type, include), f, Charsets.UTF_8); + } + + /** + * @param args + * @throws IOException + */ + public static void main(String[] args) throws IOException { + // TODO Auto-generated method stub + + Create("Integer", "Integer", ""); + Create("primint", "int" , ""); + + Create("String", "String", ""); + + Create("primdouble", "double", ""); + Create("Double", "Double", ""); + + Create("primfloat", "float", ""); + Create("Float", "Float",""); + + Create("primshort", "short", ""); + Create("Short", "Short",""); + + Create("primlong", "long", ""); + Create("Long", "Long", ""); + + Create("Boolean", "Boolean", ""); + Create("primboolean", "boolean", ""); + + Create("Byte", "Byte", ""); + Create("primbyte","byte",""); + + Create("Char", "Character", ""); + Create("primchar", "char", ""); + + Create("Date", "Date", "java.util.Date"); + + Create("ParsedURL", "ParsedURL", "ecologylab.net.ParsedURL"); + + Create("Pattern", "Pattern", "java.util.regex.Pattern"); + + Create("StringBuilder", "StringBuilder", ""); + + Create("JavaURL", "URL", "java.net.URL"); + + Create("UUID", "UUID", "java.util.UUID"); + + } + +} diff --git a/simplTests/unused/ecologylab/simpl/DBALTests.java b/simplTests/unused/ecologylab/simpl/DBALTests.java new file mode 100644 index 00000000..f8e27edf --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/DBALTests.java @@ -0,0 +1,86 @@ +package ecologylab.simpl; + +import java.util.ArrayList; + +import org.junit.Test; +import static org.junit.Assert.*; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.XMLTools; +import ecologylab.serialization.annotations.FieldUsage; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_scalar; + +public class DBALTests { + //TODO: validation on these is super sparse... just to prove out where + // exceptions happen. Will fix eventually. + + @Test + public void simpl_Collection_of_enums_transmitsNameIntoFD() + { + final class myCollectionClass + { + @simpl_collection("collection_test") + private ArrayList collectionTest; + } + + String tagName = XMLTools.getXmlTagName(myCollectionClass.class.getDeclaredFields()[0]); + assertNotNull(tagName); + System.out.println(tagName); + + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(myCollectionClass.class); + FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); + assertNotNull(fd.getTagName()); + } + + @Test + public void simpl_collection_of_composites_transmistNameIntoFD() + { + final class someCompositeClass + { + @simpl_scalar + private Integer myInteger; + } + + final class myCollectionClass + { + @simpl_collection("excluded_usage") + private ArrayList excludedUsages; + } + + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(myCollectionClass.class); + FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); + assertNotNull(fd.getTagName()); + } + + @Test + public void simpl_Collection_of_scalars_transmitsNameIntoFD() + { + final class myCollectionClass + { + @simpl_collection("excluded_usage") + private ArrayList excludedUsages; + } + + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(myCollectionClass.class); + FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); + assertNotNull(fd.getTagName()); + } + + @Test + public void simpl_collection_of_collection_of_scalars_works() + { + final class myCollectionClass + { + @simpl_collection("excluded_usage") + private ArrayList> excludedUsages; + } + + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(myCollectionClass.class); + FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); + assertNotNull(fd.getTagName()); + } + + +} diff --git a/simplTests/unused/ecologylab/simpl/DescriptorsCanBeDescribed.java b/simplTests/unused/ecologylab/simpl/DescriptorsCanBeDescribed.java new file mode 100644 index 00000000..53c5c561 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/DescriptorsCanBeDescribed.java @@ -0,0 +1,46 @@ +package ecologylab.simpl; + +import org.junit.Before; +import org.junit.Test; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.SimplTypesScope; + +public class DescriptorsCanBeDescribed{ + + + @Before + public void ResetSTS() + { + SimplTypesScope.ResetAllTypesScopes(); + } + + @Test + public void FieldDescriptorCanBeDescribed() + { + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(FieldDescriptor.class); + } + + @Test + public void ClassDescriptorCanBeDescribed() + { + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(ClassDescriptor.class); + } + + + @Test + public void YinsCase() + { + SimplTypesScope tscope = SimplTypesScope.get("test-de/serialize descriptors in json", + FieldDescriptor.class, + ClassDescriptor.class, + SimplTypesScope.class); + + } + //TODO: Better validation on these. + //They're sparse because they're just trying to catch silly exceptions. + + + +} \ No newline at end of file diff --git a/simplTests/unused/ecologylab/simpl/EnumDescriptionDeSerializationTest.java b/simplTests/unused/ecologylab/simpl/EnumDescriptionDeSerializationTest.java new file mode 100644 index 00000000..bc2414b0 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/EnumDescriptionDeSerializationTest.java @@ -0,0 +1,109 @@ +package ecologylab.simpl; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.EnumerationDescriptor; +import ecologylab.serialization.SIMPLDescriptionException; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.primaryScenarioEnum; +import ecologylab.serialization.secondaryScenarioEnum; +import ecologylab.serialization.formatenums.StringFormat; + +public class EnumDescriptionDeSerializationTest { + + + @Test + public void letsTrySomethingTricksy() + { + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(primaryScenarioEnum.class); + cd.toString(); + } + + @Test + public void EnumDescriptorCanBeDescribed() + { + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(EnumerationDescriptor.class); + } + + @Test + public void descriptionWillCorrectlySerializeToXML() throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptionTestPerFormat(primaryScenarioEnum.class, StringFormat.XML, false); + } + + @Test + public void descriptionWillCorrectlySerializeToJSON() throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptionTestPerFormat(primaryScenarioEnum.class, StringFormat.JSON, false); + } + + @Test + public void descriptionWithValuesWillCorrectlySerializeToXML() throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptionTestPerFormat(secondaryScenarioEnum.class, StringFormat.XML, true); + } + + @Test + public void descriptionWithValuesWillCorrectlySerializeToJSON() throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptionTestPerFormat(secondaryScenarioEnum.class, StringFormat.JSON, true); + } + + private void EnumerationDescriptionTestPerFormat(Class forEnumClass, StringFormat theFormat, boolean validateValues) throws SIMPLDescriptionException, SIMPLTranslationException + { + EnumerationDescriptor primaryScenario = EnumerationDescriptor.get(forEnumClass); + + SimplTypesScope sts = SimplTypesScope.get("enumTest", EnumerationDescriptor.class); + StringBuilder staticSerialized = SimplTypesScope.serialize(primaryScenario, theFormat); + StringBuilder specificSTSSerialized = sts.serialize(primaryScenario, theFormat); + + assertTrue(staticSerialized.toString().equals(specificSTSSerialized.toString())); + System.out.println(staticSerialized.toString()); + System.out.println(specificSTSSerialized.toString()); + + EnumerationDescriptor recaptured = (EnumerationDescriptor) sts.deserialize(staticSerialized.toString(), theFormat); + performBasicValidations(forEnumClass, recaptured); + + if(validateValues) + { + performValueValidation(recaptured); + } + } + + /** + * This handles some of the validations that should apply for most of the test cases; + * these have been copy pasted from the prior test case so they can be reused... + * I could have refactored this in the first test case to a method call, but I felt it was nicer w/ the core assumptions there. + * @param ed + */ + private void performBasicValidations(Class enumClass, EnumerationDescriptor ed) + { + + assertEquals("The packageName must be correct" , enumClass.getPackage().getName(), ed.getPackageName()); + assertEquals("The javaName must be correct", enumClass.getName(), ed.getJavaTypeName()); + assertEquals("The Simpl name must be correct", enumClass.getSimpleName(), ed.getName()); + + assertEquals("There should be three entries for this enum", 3, ed.getEnumerationEntries().size()); + + assertTrue("Should contain all of the values of the enum! Missing first", ed.containsEntry("firstValue")); + assertTrue("Should contain all of the values of the enum! Missing second", ed.containsEntry("secondValue")); + assertTrue("Should contain all of the values of the enum! Missing third", ed.containsEntry("thirdValue")); + assertFalse("Should not contain a value that isn't in the enum! There are no Jibbles here!", ed.containsEntry("jibbles")); + assertFalse("Should be case sensitive! FIRSTENTRY ignores casing.", ed.containsEntry("FIRSTENTRY")); + } + + private void performValueValidation(EnumerationDescriptor ed) + { + assertEquals(new Integer(3), ed.getEntryEnumIntegerValue("firstValue")); + assertEquals(new Integer(5), ed.getEntryEnumIntegerValue("secondValue")); + assertEquals(new Integer(7), ed.getEntryEnumIntegerValue("thirdValue")); + + assertEquals("firstValue", ed.getEntryEnumFromValue(3).toString()); + assertEquals("secondValue", ed.getEntryEnumFromValue(5).toString()); + assertEquals("thirdValue", ed.getEntryEnumFromValue(7).toString()); + } +} diff --git a/simplTests/unused/ecologylab/simpl/EnumerationSerializationDeserialization.java b/simplTests/unused/ecologylab/simpl/EnumerationSerializationDeserialization.java new file mode 100644 index 00000000..60683647 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/EnumerationSerializationDeserialization.java @@ -0,0 +1,125 @@ +package ecologylab.simpl; + +import static org.junit.Assert.*; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.FieldType; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.primaryScenarioEnum; +import ecologylab.serialization.secondaryScenarioEnum; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.formatenums.StringFormat; + +public class EnumerationSerializationDeserialization { + + // TODO: MAPS... OTHER FORMATS. :3 + + private void validateBasicSerializationCases(Object toSerialize, String toExpect, StringFormat format) throws SIMPLTranslationException + { + StringBuilder result = SimplTypesScope.serialize(toSerialize, format); + + System.out.println(result.toString()); + // Really sneaky way to check if firstValue is in the XML / JSON. + assertTrue(result.toString().contains(toExpect)); + } + + @Test + public void testSerializeBasicScalar() throws SIMPLTranslationException + { + basicEnumerationScalar baseCase = new basicEnumerationScalar(); + baseCase.ourEnum = primaryScenarioEnum.firstValue; + + validateBasicSerializationCases(baseCase, "firstValue", StringFormat.XML); + validateBasicSerializationCases(baseCase, "firstValue", StringFormat.JSON); + + // Should like so in XML: + // + // JSON is: {"basic_enumeration_scalar":{"our_enum":"firstValue"}} + + } + + // These are pretty much the same for serialize + // deserialize is going ot be diferent though. :3 + @Test + public void testSerializeValuedScalar() throws SIMPLTranslationException + { + customValuedEnumerationScalar valuedCase = new customValuedEnumerationScalar(); + valuedCase.ourEnum = secondaryScenarioEnum.secondValue; + + validateBasicSerializationCases(valuedCase, "secondValue", StringFormat.XML); + validateBasicSerializationCases(valuedCase, "secondValue", StringFormat.JSON); + + // + //{"custom_valued_enumeration_scalar":{"our_enum":"secondValue"}} + } + + private static SimplTypesScope ourSTS = SimplTypesScope.get("enumTestsDeSerialize", primaryScenarioEnum.class, secondaryScenarioEnum.class, + customValuedEnumerationScalar.class, basicEnumerationScalar.class, basicEnumerationList.class); + + + private void validateDeserialization(String representation, StringFormat format, Object expected) throws SIMPLTranslationException, IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException + { + Object result = ourSTS.deserialize(representation, format); + + Field ourField = result.getClass().getField("ourEnum"); + ourField.setAccessible(true); + + Object value = ourField.get(result); + assertEquals(expected, value); + } + + @Test + public void testDeserializeBaseCase() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, SIMPLTranslationException + { + basicEnumerationScalar baseCase = new basicEnumerationScalar(); + baseCase.ourEnum = primaryScenarioEnum.firstValue; + + validateDeserialization("", StringFormat.XML, primaryScenarioEnum.firstValue); + validateDeserialization("{\"basic_enumeration_scalar\":{\"our_enum\":\"secondValue\"}}", StringFormat.JSON, primaryScenarioEnum.secondValue); + } + + @Test + public void testDeserializeCustomValuedCase() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, SIMPLTranslationException + { + validateDeserialization("", StringFormat.XML, secondaryScenarioEnum.secondValue); + validateDeserialization("", StringFormat.XML, secondaryScenarioEnum.secondValue); + + validateDeserialization("{\"custom_valued_enumeration_scalar\":{\"our_enum\":\"secondValue\"}}", StringFormat.JSON, secondaryScenarioEnum.secondValue); + validateDeserialization("{\"custom_valued_enumeration_scalar\":{\"our_enum\":\"5\"}}", StringFormat.JSON, secondaryScenarioEnum.secondValue); + } + + + + @Test + public void EnumerationListsCanBeDescribed() + { + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(basicEnumerationList.class); + assertEquals(1,cd.allFieldDescriptors().size()); + + FieldDescriptor fd = (FieldDescriptor) cd.allFieldDescriptors().get(0); + + // Yeah, that's not a guarentee. I don't feel comfy making enums "elements" + // but it makes sense insofar as they rely upon the type scope. :\ + + + assertEquals(FieldType.COLLECTION_ELEMENT, fd.getType()); + assertEquals("ourEnumList", fd.getName()); + } + + + + + // TODO: Tests for lists; let's get the base case fixed first. + + + + +} diff --git a/simplTests/unused/ecologylab/simpl/FieldDescriptionTest.java b/simplTests/unused/ecologylab/simpl/FieldDescriptionTest.java new file mode 100644 index 00000000..0d9bdf5c --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/FieldDescriptionTest.java @@ -0,0 +1,35 @@ +package ecologylab.simpl; + +import org.junit.Test; +import static org.junit.Assert.*; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.FieldType; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.primaryScenarioEnum; +import ecologylab.serialization.annotations.simpl_scalar; + +public class FieldDescriptionTest { + + @Test + public void testDescribeEnumerationField() throws SIMPLTranslationException{ + final class anEnumField + { + @simpl_scalar + private primaryScenarioEnum myEnum; + } + + ClassDescriptor cd = ClassDescriptor.getClassDescriptor(anEnumField.class); + assertEquals(1,cd.allFieldDescriptors().size()); + + FieldDescriptor fd = (FieldDescriptor)cd.allFieldDescriptors().get(0); + assertEquals(FieldType.SCALAR, fd.getType()); + assertEquals(primaryScenarioEnum.class, fd.getFieldType()); + assertEquals(true, fd.isEnum()); + assertNotNull(fd.getEnumerationDescriptor()); + assertEquals("firstValue", fd.getEnumerationDescriptor().marshal(primaryScenarioEnum.firstValue)); + assertEquals(primaryScenarioEnum.firstValue, fd.getEnumerationDescriptor().unmarshal("firstValue")); + + } +} diff --git a/simplTests/unused/ecologylab/simpl/ListDeSerializationTests.java b/simplTests/unused/ecologylab/simpl/ListDeSerializationTests.java new file mode 100644 index 00000000..5d03d525 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/ListDeSerializationTests.java @@ -0,0 +1,154 @@ +package ecologylab.simpl; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.primaryScenarioEnum; +import ecologylab.serialization.secondaryScenarioEnum; +import ecologylab.serialization.formatenums.StringFormat; + +public class ListDeSerializationTests { + + + private static SimplTypesScope ourSTS = SimplTypesScope.get("enumTestsDeSerialize", primaryScenarioEnum.class, secondaryScenarioEnum.class, + customValuedEnumerationScalar.class, basicEnumerationScalar.class, basicEnumerationList.class, basicScalarList.class, basicComposite.class, basicCompositeList.class); + @Test + public void EnumerationListsSerialize() + { + fail("You haven't picked a format yet, Tom. Pick one."); + } + + @Test + public void EnumerationListsDeserialize() throws SIMPLTranslationException + { + List ourList = new ArrayList(); + ourList.add(primaryScenarioEnum.firstValue); + ourList.add(primaryScenarioEnum.secondValue); + ourList.add(primaryScenarioEnum.thirdValue); + + basicEnumerationList bel = new basicEnumerationList(); + bel.ourList = ourList; + + StringBuilder result = ourSTS.serialize(bel, StringFormat.XML); + basicEnumerationList after = (basicEnumerationList) ourSTS.deserialize(result.toString(), StringFormat.XML); + + assertNotNull(after.ourList); + assertEquals(3, after.ourList.size()); + for(int i = 0; i < 3; i++) + { + assertEquals(bel.ourList.get(i), after.ourList.get(i)); + } + } + + + @Test + public void ScalarListsDeserializeXML() throws SIMPLTranslationException + { + testScalarListSerialization(StringFormat.XML); + } + + @Test + public void ScalarListsDeserializeJSON() throws SIMPLTranslationException + { + testScalarListSerialization(StringFormat.JSON); + } + + private void testScalarListSerialization(StringFormat format) throws SIMPLTranslationException + { + List myList = new ArrayList(); + myList.add(0); + myList.add(1); + myList.add(2); + + basicScalarList bel = new basicScalarList(); + bel.ourList = myList; + + StringBuilder result = ourSTS.serialize(bel, format); + + System.out.println(result.toString()); + + basicScalarList after = (basicScalarList) ourSTS.deserialize(result.toString(), format); + + assertNotNull(after.ourList); + assertEquals("Missing elements from the list!", 3, after.ourList.size()); + for(int i = 0; i < 3; i++) + { + assertEquals(bel.ourList.get(i), after.ourList.get(i)); + } + } + + @Test + public void basicCompositeDeserializesXML() throws SIMPLTranslationException + { + for(int i = -3; i < 4; i++) + { + testABasicComposite(i, StringFormat.XML); + } + } + + @Test + public void basicCompositeDeserializesJSON() throws SIMPLTranslationException + { + for(int i = -3; i < 4; i++) + { + testABasicComposite(i, StringFormat.JSON); + } + } + + private void testABasicComposite(int i, StringFormat format) throws SIMPLTranslationException + { + basicComposite bc = new basicComposite(i); + + assertEquals("value in bc.a was incorrect.", new Integer(i),bc.a); + assertEquals("value in bc.b was incorrect.", i+1,bc.b); + + StringBuilder result = ourSTS.serialize(bc, format); + basicComposite after = (basicComposite) ourSTS.deserialize(result.toString(), format); + + assertEquals("Values incorrect for a after roundtrip.", bc.a, after.a); + assertEquals("Values incorrect for b after roundtrip.", bc.b, after.b); + } + + @Test + public void CompositeListsDeserializeJSON() throws SIMPLTranslationException + { + testCompositeList(StringFormat.JSON); + } + + @Test + public void CompositeListsDeserializeXML() throws SIMPLTranslationException + { + testCompositeList(StringFormat.XML); + } + + + private void testCompositeList(StringFormat format) throws SIMPLTranslationException + { + List myList = new ArrayList(); + myList.add(new basicComposite(0)); + myList.add(new basicComposite(1)); + myList.add(new basicComposite(2)); + + basicCompositeList bel = new basicCompositeList(); + bel.ourList = myList; + + StringBuilder result = ourSTS.serialize(bel, format); + basicCompositeList after = (basicCompositeList) ourSTS.deserialize(result.toString(), format); + + assertNotNull(after.ourList); + assertEquals("Missing elements from the list!",3, after.ourList.size()); + for(int i = 0; i < 3; i++) + { + assertEquals("Values incorrect for rountrip for a: ", bel.ourList.get(i).a, after.ourList.get(i).a); + assertEquals("Values incorrect for rountrip for b: ", bel.ourList.get(i).b, after.ourList.get(i).b); + } + } +} diff --git a/simplTests/unused/ecologylab/simpl/MultiIndexerTest.java b/simplTests/unused/ecologylab/simpl/MultiIndexerTest.java new file mode 100644 index 00000000..fa2a7cc2 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/MultiIndexerTest.java @@ -0,0 +1,53 @@ +package ecologylab.simpl; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import ecologylab.generic.MultiIndexer; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.ClassDescriptorIndexer; + +public class MultiIndexerTest { + + @Test + public void testInsert() { + + final class myClass{ + } + + MultiIndexer> sut = new ClassDescriptorIndexer(); + + ClassDescriptor relevant = ClassDescriptor.getClassDescriptor(myClass.class); + + sut.Insert(relevant); + + ClassDescriptor result = sut.by("simplname").get(relevant.getClassSimpleName()); + + assertEquals(relevant, result); + assertTrue(1==sut.size()); + + + } + + @Test + public void testRemove() + { + final class myClass{} + + MultiIndexer> sut = new ClassDescriptorIndexer(); + + ClassDescriptor relevant = ClassDescriptor.getClassDescriptor(myClass.class); + + sut.Insert(relevant); + + assertTrue(1==sut.size()); + + sut.Remove(relevant); + + assertTrue(0==sut.size()); + + assertNull(sut.by("simplname").get(relevant.getClassSimpleName())); + } + +} diff --git a/simplTests/unused/ecologylab/simpl/RoundtripTestsProvisional.java b/simplTests/unused/ecologylab/simpl/RoundtripTestsProvisional.java new file mode 100644 index 00000000..3de318c1 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/RoundtripTestsProvisional.java @@ -0,0 +1,58 @@ +package ecologylab.simpl; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.StringFormat; + +public class RoundtripTestsProvisional { + + @Test + public void testJSONRoundtripWithTrickyString() throws SIMPLTranslationException { + + + TrickyString ts = new TrickyString(); + ts.trickyString = "\" \\ / // <<< >>> {}{}{} {>>> == =:: / / / /_ -- --__ : : \b a \f b \n c \n d \r e \t f"; // we choke on unicode, for now \u1337"; + System.out.println(ts.trickyString); + + StringBuilder serialized = SimplTypesScope.serialize(ts, StringFormat.JSON); + System.out.println(serialized.toString()); + + SimplTypesScope sts = SimplTypesScope.get("stringTest", TrickyString.class); + + Object result = sts.deserialize(serialized.toString(), StringFormat.JSON); + assertTrue(result.getClass().equals(TrickyString.class)); + TrickyString otherString = (TrickyString)result; + + System.out.println(otherString.trickyString); + + assertEquals(ts.trickyString, otherString.trickyString); + } + + @Test + public void testXMLRoundtripWithTrickyString() throws SIMPLTranslationException { + + + TrickyString ts = new TrickyString(); + ts.trickyString = "< >> <<<<< >>>> ><<><><>< \"/ '' = = = = ;: === \": ' \\\"\\\"\\\\\" '\" \\ / // / / / /_ -- --__ : : \b a \f b \n c \n d \r e \t f"; //We choke on unicode, for now. \u1337"; + System.out.println(ts.trickyString); + + StringBuilder serialized = SimplTypesScope.serialize(ts, StringFormat.XML); + System.out.println(serialized.toString()); + + SimplTypesScope sts = SimplTypesScope.get("stringTest", TrickyString.class); + + Object result = sts.deserialize(serialized.toString(), StringFormat.XML); + assertTrue(result.getClass().equals(TrickyString.class)); + TrickyString otherString = (TrickyString)result; + + System.out.println(otherString.trickyString); + + assertEquals(ts.trickyString, otherString.trickyString); + } + + +} diff --git a/simplTests/unused/ecologylab/simpl/SimplTypesScopeTest.java b/simplTests/unused/ecologylab/simpl/SimplTypesScopeTest.java new file mode 100644 index 00000000..e7498eab --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/SimplTypesScopeTest.java @@ -0,0 +1,14 @@ +package ecologylab.simpl; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class SimplTypesScopeTest { + + @Test + public void test() { + fail("Not yet implemented"); + } + +} diff --git a/simplTests/unused/ecologylab/simpl/TrickyString.java b/simplTests/unused/ecologylab/simpl/TrickyString.java new file mode 100644 index 00000000..fdeee298 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/TrickyString.java @@ -0,0 +1,11 @@ +package ecologylab.simpl; + +import ecologylab.serialization.annotations.simpl_scalar; + +public class TrickyString +{ + @simpl_scalar + public String trickyString; + + public TrickyString(){} +} diff --git a/simplTests/unused/ecologylab/simpl/ValidateSimplScalarTestMechanism.java b/simplTests/unused/ecologylab/simpl/ValidateSimplScalarTestMechanism.java new file mode 100644 index 00000000..a5984a6d --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/ValidateSimplScalarTestMechanism.java @@ -0,0 +1,12 @@ +package ecologylab.simpl; + +import org.junit.Test; + +public class ValidateSimplScalarTestMechanism { + + @Test + public void IteratesThroughAllTestClasses() + { + + } +} diff --git a/simplTests/unused/ecologylab/simpl/basicComposite.java b/simplTests/unused/ecologylab/simpl/basicComposite.java new file mode 100644 index 00000000..3962d90e --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/basicComposite.java @@ -0,0 +1,19 @@ +package ecologylab.simpl; + +import ecologylab.serialization.annotations.simpl_scalar; + +public class basicComposite { + + @simpl_scalar + public Integer a; + @simpl_scalar + public int b; + + public basicComposite(){} + + public basicComposite(int i) + { + this.a = i; + this.b = i+1; + } +} diff --git a/simplTests/unused/ecologylab/simpl/basicCompositeList.java b/simplTests/unused/ecologylab/simpl/basicCompositeList.java new file mode 100644 index 00000000..ac8baedb --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/basicCompositeList.java @@ -0,0 +1,17 @@ +package ecologylab.simpl; + +import java.util.ArrayList; +import java.util.List; + +import ecologylab.serialization.annotations.simpl_collection; + +public class basicCompositeList { + + @simpl_collection("collect") + public List ourList; + + public basicCompositeList() + { + ourList = new ArrayList(); + } +} diff --git a/simplTests/unused/ecologylab/simpl/basicEnumerationList.java b/simplTests/unused/ecologylab/simpl/basicEnumerationList.java new file mode 100644 index 00000000..ea6519fb --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/basicEnumerationList.java @@ -0,0 +1,17 @@ +package ecologylab.simpl; + +import java.util.ArrayList; +import java.util.List; + +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.primaryScenarioEnum; + + + +public class basicEnumerationList { + + @simpl_collection("collect") + public List ourList; + + public basicEnumerationList(){ ourList = new ArrayList(); } +} diff --git a/simplTests/unused/ecologylab/simpl/basicEnumerationScalar.java b/simplTests/unused/ecologylab/simpl/basicEnumerationScalar.java new file mode 100644 index 00000000..0bda4102 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/basicEnumerationScalar.java @@ -0,0 +1,12 @@ +package ecologylab.simpl; + +import ecologylab.serialization.primaryScenarioEnum; +import ecologylab.serialization.annotations.simpl_scalar; + +final class basicEnumerationScalar +{ + @simpl_scalar + public primaryScenarioEnum ourEnum; + + public basicEnumerationScalar(){}; +} \ No newline at end of file diff --git a/simplTests/unused/ecologylab/simpl/basicScalarList.java b/simplTests/unused/ecologylab/simpl/basicScalarList.java new file mode 100644 index 00000000..a8149835 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/basicScalarList.java @@ -0,0 +1,17 @@ +package ecologylab.simpl; + +import java.util.ArrayList; +import java.util.List; + +import ecologylab.serialization.annotations.simpl_collection; + +public class basicScalarList { + + @simpl_collection("collect") + public List ourList; + + public basicScalarList() + { + ourList = new ArrayList(); + } +} diff --git a/simplTests/unused/ecologylab/simpl/customValuedEnumerationScalar.java b/simplTests/unused/ecologylab/simpl/customValuedEnumerationScalar.java new file mode 100644 index 00000000..3f9cbd1d --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/customValuedEnumerationScalar.java @@ -0,0 +1,15 @@ +package ecologylab.simpl; + +import ecologylab.serialization.secondaryScenarioEnum; +import ecologylab.serialization.annotations.simpl_scalar; + +final class customValuedEnumerationScalar +{ + @simpl_scalar + public secondaryScenarioEnum ourEnum; + + public customValuedEnumerationScalar() + { + + } +} \ No newline at end of file diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleBoolean.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleBoolean.java new file mode 100644 index 00000000..9cb0280c --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleBoolean.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleBoolean { + @simpl_scalar + private Boolean simpleboolean; + + public Boolean getSimpleBoolean(){ + return this.simpleboolean; + } + + public void setSimpleBoolean(Boolean value){ + this.simpleboolean = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleByte.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleByte.java new file mode 100644 index 00000000..de96b0df --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleByte.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleByte { + @simpl_scalar + private Byte simplebyte; + + public Byte getSimpleByte(){ + return this.simplebyte; + } + + public void setSimpleByte(Byte value){ + this.simplebyte = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleChar.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleChar.java new file mode 100644 index 00000000..0b98b856 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleChar.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleChar { + @simpl_scalar + private Character simplechar; + + public Character getSimpleChar(){ + return this.simplechar; + } + + public void setSimpleChar(Character value){ + this.simplechar = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleDate.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleDate.java new file mode 100644 index 00000000..5057314e --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleDate.java @@ -0,0 +1,15 @@ +package ecologylab.simpl.simplescalar; +import java.util.Date; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleDate { + @simpl_scalar + private Date simpledate; + + public Date getSimpleDate(){ + return this.simpledate; + } + + public void setSimpleDate(Date value){ + this.simpledate = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleDouble.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleDouble.java new file mode 100644 index 00000000..6ba2a203 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleDouble.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleDouble { + @simpl_scalar + private Double simpledouble; + + public Double getSimpleDouble(){ + return this.simpledouble; + } + + public void setSimpleDouble(Double value){ + this.simpledouble = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleFloat.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleFloat.java new file mode 100644 index 00000000..1eaf9951 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleFloat.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleFloat { + @simpl_scalar + private Float simplefloat; + + public Float getSimpleFloat(){ + return this.simplefloat; + } + + public void setSimpleFloat(Float value){ + this.simplefloat = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleInteger.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleInteger.java new file mode 100644 index 00000000..6589deb6 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleInteger.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleInteger { + @simpl_scalar + private Integer simpleinteger; + + public Integer getSimpleInteger(){ + return this.simpleinteger; + } + + public void setSimpleInteger(Integer value){ + this.simpleinteger = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleJavaURL.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleJavaURL.java new file mode 100644 index 00000000..809b3331 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleJavaURL.java @@ -0,0 +1,15 @@ +package ecologylab.simpl.simplescalar; +import java.net.URL; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleJavaURL { + @simpl_scalar + private URL simplejavaurl; + + public URL getSimpleJavaURL(){ + return this.simplejavaurl; + } + + public void setSimpleJavaURL(URL value){ + this.simplejavaurl = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleLong.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleLong.java new file mode 100644 index 00000000..2ca94be3 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleLong.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleLong { + @simpl_scalar + private Long simplelong; + + public Long getSimpleLong(){ + return this.simplelong; + } + + public void setSimpleLong(Long value){ + this.simplelong = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleParsedURL.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleParsedURL.java new file mode 100644 index 00000000..792d00c2 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleParsedURL.java @@ -0,0 +1,15 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleParsedURL { + @simpl_scalar + private ParsedURL simpleparsedurl; + + public ParsedURL getSimpleParsedURL(){ + return this.simpleparsedurl; + } + + public void setSimpleParsedURL(ParsedURL value){ + this.simpleparsedurl = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimplePattern.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimplePattern.java new file mode 100644 index 00000000..4fd5b0cd --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimplePattern.java @@ -0,0 +1,15 @@ +package ecologylab.simpl.simplescalar; +import java.util.regex.Pattern; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimplePattern { + @simpl_scalar + private Pattern simplepattern; + + public Pattern getSimplePattern(){ + return this.simplepattern; + } + + public void setSimplePattern(Pattern value){ + this.simplepattern = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleShort.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleShort.java new file mode 100644 index 00000000..1b0ac4b5 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleShort.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleShort { + @simpl_scalar + private Short simpleshort; + + public Short getSimpleShort(){ + return this.simpleshort; + } + + public void setSimpleShort(Short value){ + this.simpleshort = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleString.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleString.java new file mode 100644 index 00000000..9a21e760 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleString.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleString { + @simpl_scalar + private String simplestring; + + public String getSimpleString(){ + return this.simplestring; + } + + public void setSimpleString(String value){ + this.simplestring = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleStringBuilder.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleStringBuilder.java new file mode 100644 index 00000000..f47ffbb5 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleStringBuilder.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleStringBuilder { + @simpl_scalar + private StringBuilder simplestringbuilder; + + public StringBuilder getSimpleStringBuilder(){ + return this.simplestringbuilder; + } + + public void setSimpleStringBuilder(StringBuilder value){ + this.simplestringbuilder = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/SimpleUUID.java b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleUUID.java new file mode 100644 index 00000000..80fa273a --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/SimpleUUID.java @@ -0,0 +1,15 @@ +package ecologylab.simpl.simplescalar; +import java.util.UUID; +import ecologylab.serialization.annotations.simpl_scalar; +public class SimpleUUID { + @simpl_scalar + private UUID simpleuuid; + + public UUID getSimpleUUID(){ + return this.simpleuuid; + } + + public void setSimpleUUID(UUID value){ + this.simpleuuid = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimboolean.java b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimboolean.java new file mode 100644 index 00000000..460833c5 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimboolean.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimboolean { + @simpl_scalar + private boolean simpleprimboolean; + + public boolean getSimpleprimboolean(){ + return this.simpleprimboolean; + } + + public void setSimpleprimboolean(boolean value){ + this.simpleprimboolean = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimbyte.java b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimbyte.java new file mode 100644 index 00000000..f87d4c45 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimbyte.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimbyte { + @simpl_scalar + private byte simpleprimbyte; + + public byte getSimpleprimbyte(){ + return this.simpleprimbyte; + } + + public void setSimpleprimbyte(byte value){ + this.simpleprimbyte = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimchar.java b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimchar.java new file mode 100644 index 00000000..c90a8bfe --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimchar.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimchar { + @simpl_scalar + private char simpleprimchar; + + public char getSimpleprimchar(){ + return this.simpleprimchar; + } + + public void setSimpleprimchar(char value){ + this.simpleprimchar = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimdouble.java b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimdouble.java new file mode 100644 index 00000000..a1fc85b8 --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimdouble.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimdouble { + @simpl_scalar + private double simpleprimdouble; + + public double getSimpleprimdouble(){ + return this.simpleprimdouble; + } + + public void setSimpleprimdouble(double value){ + this.simpleprimdouble = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimfloat.java b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimfloat.java new file mode 100644 index 00000000..4f24b36a --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimfloat.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimfloat { + @simpl_scalar + private float simpleprimfloat; + + public float getSimpleprimfloat(){ + return this.simpleprimfloat; + } + + public void setSimpleprimfloat(float value){ + this.simpleprimfloat = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimint.java b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimint.java new file mode 100644 index 00000000..8417568f --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimint.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimint { + @simpl_scalar + private int simpleprimint; + + public int getSimpleprimint(){ + return this.simpleprimint; + } + + public void setSimpleprimint(int value){ + this.simpleprimint = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimlong.java b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimlong.java new file mode 100644 index 00000000..6bf08b6a --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimlong.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimlong { + @simpl_scalar + private long simpleprimlong; + + public long getSimpleprimlong(){ + return this.simpleprimlong; + } + + public void setSimpleprimlong(long value){ + this.simpleprimlong = value; + } +} diff --git a/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimshort.java b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimshort.java new file mode 100644 index 00000000..dd7f31dd --- /dev/null +++ b/simplTests/unused/ecologylab/simpl/simplescalar/Simpleprimshort.java @@ -0,0 +1,14 @@ +package ecologylab.simpl.simplescalar; +import ecologylab.serialization.annotations.simpl_scalar; +public class Simpleprimshort { + @simpl_scalar + private short simpleprimshort; + + public short getSimpleprimshort(){ + return this.simpleprimshort; + } + + public void setSimpleprimshort(short value){ + this.simpleprimshort = value; + } +} diff --git a/simplTranslators/.classpath b/simplTranslators/.classpath index 6bc2aaab..023d5536 100644 --- a/simplTranslators/.classpath +++ b/simplTranslators/.classpath @@ -1,16 +1,15 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/simplTranslators/.gitignore b/simplTranslators/.gitignore deleted file mode 100644 index 0036f6e4..00000000 --- a/simplTranslators/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -#java specific -*.class - -#netbeans ignore personal stuff -nbproject/private/ - - -## generic files to ignore -*~ -*.lock -*.DS_Store -*.swp -*.out - -.settings/ -bin/ - diff --git a/simplTranslators/build.xml b/simplTranslators/build.xml index 658cfdcc..e6073d67 100644 --- a/simplTranslators/build.xml +++ b/simplTranslators/build.xml @@ -1,160 +1,13 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - compiling project ${project.name} ... - - - - - - - - - - - List of projects to build: ${buildorder} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - building project ${project.name} - - - - - - - - - - - - - - - - - Jar'ing project ${project.name} from ${myOutputpath} - - - - - - - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/simplTranslators/jscode/gamething.js b/simplTranslators/jscode/gamething.js index ef9a0373..56b22b43 100644 --- a/simplTranslators/jscode/gamething.js +++ b/simplTranslators/jscode/gamething.js @@ -1,261 +1,261 @@ - -function field_descriptor(json,name,tag_name,other_tags,comment,field,element_class_descriptor,map_key_field_name,declaring_class_descriptor,element_class,is_generic,polymorph_class_descriptors,polymorph_classes,library_namespaces,type,scalar_type,collection_type,xml_hint,is_enum,is_c_d_a_t_a,needs_escaping,filter_regex,filter_replace,unresolved_scope_annotation,collection_or_map_tag_name,composite_tag_name,wrapped,field_type,generic_parameters_string) -{ - this._simpl_object_name = "field_descriptor"; - this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.serialization.FieldDescriptor", "tag_name":"field_descriptor", "described_class":"ecologylab.serialization.FieldDescriptor", "described_class_simple_name":"FieldDescriptor", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1893488603", "super_class":{"name":"ecologylab.serialization.DescriptorBase", "tag_name":"descriptor_base", "described_class":"ecologylab.serialization.DescriptorBase", "described_class_simple_name":"DescriptorBase", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1530970753", "super_class":{"name":"ecologylab.serialization.types.SimplBaseType", "tag_name":"simpl_base_type", "described_class":"ecologylab.serialization.types.SimplBaseType", "described_class_simple_name":"SimplBaseType", "described_class_package_name":"ecologylab.serialization.types", "simpl.id":"2023870964", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "other_tag":["field_name","described_class_name"], "declaring_class_descriptor":{"simpl.ref":"2023870964"}}]}, "field_descriptor":[{"name":"tagName", "tag_name":"tag_name", "field":"tagName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1530970753"}},{"name":"otherTags", "tag_name":"other_tags", "field":"otherTags", "is_generic":"true", "type":"5", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"other_tag", "field_type":"ArrayList", "generic_parameters_string":"<String>", "declaring_class_descriptor":{"simpl.ref":"1530970753"}, "collection_type":{"name":"simpl.types.collection.ArrayList", "simple_name":"ArrayList", "java_type_name":"java.util.ArrayList", "c_sharp_type_name":"List", "objective_c_type_name":"NSMutableArray", "package_name":"java.util", "simpl.id":"792386646"}},{"name":"comment", "tag_name":"comment", "field":"comment", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1530970753"}}]}, "field_descriptor":[{"name":"field", "tag_name":"field", "field":"field", "type":"18", "scalar_type":"Field", "xml_hint":"XML_ATTRIBUTE", "field_type":"Field", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"elementClassDescriptor", "tag_name":"element_class_descriptor", "field":"elementClassDescriptor", "element_class":"ecologylab.serialization.ClassDescriptor", "type":"3", "composite_tag_name":"element_class_descriptor", "field_type":"ClassDescriptor", "element_class_descriptor":{"name":"ecologylab.serialization.ClassDescriptor", "tag_name":"class_descriptor", "described_class":"ecologylab.serialization.ClassDescriptor", "described_class_simple_name":"ClassDescriptor", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1551083435", "super_class":{"simpl.ref":"1530970753"}, "field_descriptor":[{"name":"describedClass", "tag_name":"described_class", "field":"describedClass", "is_generic":"true", "type":"18", "scalar_type":"Class", "xml_hint":"XML_ATTRIBUTE", "field_type":"Class", "generic_parameters_string":"<?>", "declaring_class_descriptor":{"simpl.ref":"1551083435"}},{"name":"describedClassSimpleName", "tag_name":"described_class_simple_name", "field":"describedClassSimpleName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1551083435"}},{"name":"describedClassPackageName", "tag_name":"described_class_package_name", "field":"describedClassPackageName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1551083435"}},{"name":"superClass", "tag_name":"super_class", "field":"superClass", "element_class":"ecologylab.serialization.ClassDescriptor", "type":"3", "composite_tag_name":"super_class", "field_type":"ClassDescriptor", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}},{"name":"interfaces", "tag_name":"interfaces", "field":"interfaces", "is_generic":"true", "type":"5", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"interface", "wrapped":"true", "field_type":"ArrayList", "generic_parameters_string":"<String>", "other_tag":["inerface"], "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "collection_type":{"simpl.ref":"792386646"}},{"name":"declaredFieldDescriptorsByFieldName", "tag_name":"declared_field_descriptors_by_field_name", "field":"declaredFieldDescriptorsByFieldName", "map_key_field_name":"name", "element_class":"ecologylab.serialization.FieldDescriptor", "is_generic":"true", "type":"6", "collection_or_map_tag_name":"field_descriptor", "field_type":"HashMapArrayList", "generic_parameters_string":"<String, ?>", "element_class_descriptor":{"simpl.ref":"1893488603"}, "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "collection_type":{"name":"ecologylab.generic.HashMapArrayList", "simple_name":"HashMapArrayList", "java_type_name":"ecologylab.generic.HashMapArrayList", "c_sharp_type_name":"DictionaryList", "objective_c_type_name":"NSDictionaryList", "package_name":"ecologylab.generic", "is_map":"true", "simpl.id":"1967571412"}},{"name":"genericTypeVariables", "tag_name":"generic_type_variables", "field":"genericTypeVariables", "is_generic":"true", "type":"5", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"generic_type_variable", "wrapped":"true", "field_type":"ArrayList", "generic_parameters_string":"<String>", "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "collection_type":{"simpl.ref":"792386646"}},{"name":"strictObjectGraphRequired", "tag_name":"strict_object_graph_required", "field":"strictObjectGraphRequired", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1551083435"}}], "generic_type_variables":{"generic_type_variable":["ES","FD"]}}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}},{"name":"mapKeyFieldName", "tag_name":"map_key_field_name", "field":"mapKeyFieldName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"declaringClassDescriptor", "tag_name":"declaring_class_descriptor", "field":"declaringClassDescriptor", "element_class":"ecologylab.serialization.ClassDescriptor", "type":"3", "composite_tag_name":"declaring_class_descriptor", "field_type":"ClassDescriptor", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}},{"name":"elementClass", "tag_name":"element_class", "field":"elementClass", "type":"18", "scalar_type":"Class", "xml_hint":"XML_ATTRIBUTE", "field_type":"Class", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"isGeneric", "tag_name":"is_generic", "field":"isGeneric", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"polymorphClassDescriptors", "tag_name":"polymorph_class_descriptors", "field":"polymorphClassDescriptors", "map_key_field_name":"tagName", "element_class":"ecologylab.serialization.ClassDescriptor", "is_generic":"true", "type":"6", "collection_or_map_tag_name":"polymorph_class_descriptor", "wrapped":"true", "field_type":"HashMapArrayList", "generic_parameters_string":"<String, ClassDescriptor>", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}, "collection_type":{"simpl.ref":"1967571412"}},{"name":"polymorphClasses", "tag_name":"polymorph_classes", "field":"polymorphClasses", "is_generic":"true", "type":"7", "scalar_type":"Class", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"polymorph_class", "wrapped":"true", "field_type":"HashMap", "generic_parameters_string":"<String, Class>", "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "collection_type":{"name":"simpl.types.collection.HashMap", "simple_name":"HashMap", "java_type_name":"java.util.HashMap", "c_sharp_type_name":"Dictionary", "objective_c_type_name":"NSDictionary", "package_name":"java.util", "is_map":"true", "simpl.id":"855703640"}},{"name":"libraryNamespaces", "tag_name":"library_namespaces", "field":"libraryNamespaces", "is_generic":"true", "type":"7", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"library_namespace", "wrapped":"true", "field_type":"HashMap", "generic_parameters_string":"<String, String>", "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "collection_type":{"simpl.ref":"855703640"}},{"name":"type", "tag_name":"type", "field":"type", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"scalarType", "tag_name":"scalar_type", "field":"scalarType", "is_generic":"true", "type":"18", "scalar_type":"ScalarType", "xml_hint":"XML_ATTRIBUTE", "field_type":"ScalarType", "generic_parameters_string":"<?>", "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization.types"]}},{"name":"collectionType", "tag_name":"collection_type", "field":"collectionType", "element_class":"ecologylab.serialization.types.CollectionType", "type":"3", "composite_tag_name":"collection_type", "field_type":"CollectionType", "element_class_descriptor":{"name":"ecologylab.serialization.types.CollectionType", "tag_name":"collection_type", "described_class":"ecologylab.serialization.types.CollectionType", "described_class_simple_name":"CollectionType", "described_class_package_name":"ecologylab.serialization.types", "simpl.id":"700804192", "super_class":{"name":"ecologylab.serialization.types.SimplType", "tag_name":"simpl_type", "described_class":"ecologylab.serialization.types.SimplType", "described_class_simple_name":"SimplType", "described_class_package_name":"ecologylab.serialization.types", "simpl.id":"1615734796", "super_class":{"simpl.ref":"2023870964"}, "field_descriptor":[{"name":"simpleName", "tag_name":"simple_name", "field":"simpleName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"javaTypeName", "tag_name":"java_type_name", "field":"javaTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"cSharpTypeName", "tag_name":"c_sharp_type_name", "field":"cSharpTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"objectiveCTypeName", "tag_name":"objective_c_type_name", "field":"objectiveCTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"dbTypeName", "tag_name":"db_type_name", "field":"dbTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"packageName", "tag_name":"package_name", "field":"packageName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}}], "generic_type_variables":{"generic_type_variable":["T"]}}, "field_descriptor":[{"name":"isMap", "tag_name":"is_map", "field":"isMap", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"700804192"}}], "generic_type_variables":{"generic_type_variable":["T"]}}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization.types"]}},{"name":"xmlHint", "tag_name":"xml_hint", "field":"xmlHint", "type":"18", "scalar_type":"Enum", "xml_hint":"XML_ATTRIBUTE", "is_enum":"true", "field_type":"Hint", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"isEnum", "tag_name":"is_enum", "field":"isEnum", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"isCDATA", "tag_name":"is_c_d_a_t_a", "field":"isCDATA", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"needsEscaping", "tag_name":"needs_escaping", "field":"needsEscaping", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"filterRegex", "tag_name":"filter_regex", "field":"filterRegex", "type":"18", "scalar_type":"Pattern", "xml_hint":"XML_ATTRIBUTE", "field_type":"Pattern", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"filterReplace", "tag_name":"filter_replace", "field":"filterReplace", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"unresolvedScopeAnnotation", "tag_name":"unresolved_scope_annotation", "field":"unresolvedScopeAnnotation", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"collectionOrMapTagName", "tag_name":"collection_or_map_tag_name", "field":"collectionOrMapTagName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"compositeTagName", "tag_name":"composite_tag_name", "field":"compositeTagName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"wrapped", "tag_name":"wrapped", "field":"wrapped", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"fieldType", "tag_name":"field_type", "field":"fieldType", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"genericParametersString", "tag_name":"generic_parameters_string", "field":"genericParametersString", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}}]}}'; - this._simpl_collection_types = {}; - this._simpl_map_types = {"polymorph_class_descriptors":"class_descriptor","polymorph_classes":"object","library_namespaces":"object"}; - this._simpl_map_types_keys = {"polymorph_class_descriptors":"tag_name","polymorph_classes":"object","library_namespaces":"object"}; - this._simpl_composite_types = {"element_class_descriptor":"class_descriptor","declaring_class_descriptor":"class_descriptor","collection_type":"collection_type"}; - if(json) - { - jsonConstruct(json,this); - return; - } - else - { - if(name) this.name = name; - if(tag_name) this.tag_name = tag_name; - if(other_tags) this.other_tags = other_tags; - if(comment) this.comment = comment; - if(field) this.field = field; - if(element_class_descriptor) this.element_class_descriptor = element_class_descriptor; - if(map_key_field_name) this.map_key_field_name = map_key_field_name; - if(declaring_class_descriptor) this.declaring_class_descriptor = declaring_class_descriptor; - if(element_class) this.element_class = element_class; - if(is_generic) this.is_generic = is_generic; - if(polymorph_class_descriptors) this.polymorph_class_descriptors = polymorph_class_descriptors; - if(polymorph_classes) this.polymorph_classes = polymorph_classes; - if(library_namespaces) this.library_namespaces = library_namespaces; - if(type) this.type = type; - if(scalar_type) this.scalar_type = scalar_type; - if(collection_type) this.collection_type = collection_type; - if(xml_hint) this.xml_hint = xml_hint; - if(is_enum) this.is_enum = is_enum; - if(is_c_d_a_t_a) this.is_c_d_a_t_a = is_c_d_a_t_a; - if(needs_escaping) this.needs_escaping = needs_escaping; - if(filter_regex) this.filter_regex = filter_regex; - if(filter_replace) this.filter_replace = filter_replace; - if(unresolved_scope_annotation) this.unresolved_scope_annotation = unresolved_scope_annotation; - if(collection_or_map_tag_name) this.collection_or_map_tag_name = collection_or_map_tag_name; - if(composite_tag_name) this.composite_tag_name = composite_tag_name; - if(wrapped) this.wrapped = wrapped; - if(field_type) this.field_type = field_type; - if(generic_parameters_string) this.generic_parameters_string = generic_parameters_string; - } -} - - -function class_descriptor(json,name,tag_name,other_tags,comment,described_class,described_class_simple_name,described_class_package_name,super_class,interfaces,field_descriptor,generic_type_variables,strict_object_graph_required) -{ - this._simpl_object_name = "class_descriptor"; - this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.serialization.ClassDescriptor", "tag_name":"class_descriptor", "described_class":"ecologylab.serialization.ClassDescriptor", "described_class_simple_name":"ClassDescriptor", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1551083435", "super_class":{"name":"ecologylab.serialization.DescriptorBase", "tag_name":"descriptor_base", "described_class":"ecologylab.serialization.DescriptorBase", "described_class_simple_name":"DescriptorBase", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1530970753", "super_class":{"name":"ecologylab.serialization.types.SimplBaseType", "tag_name":"simpl_base_type", "described_class":"ecologylab.serialization.types.SimplBaseType", "described_class_simple_name":"SimplBaseType", "described_class_package_name":"ecologylab.serialization.types", "simpl.id":"2023870964", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "other_tag":["field_name","described_class_name"], "declaring_class_descriptor":{"simpl.ref":"2023870964"}}]}, "field_descriptor":[{"name":"tagName", "tag_name":"tag_name", "field":"tagName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1530970753"}},{"name":"otherTags", "tag_name":"other_tags", "field":"otherTags", "is_generic":"true", "type":"5", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"other_tag", "field_type":"ArrayList", "generic_parameters_string":"<String>", "declaring_class_descriptor":{"simpl.ref":"1530970753"}, "collection_type":{"name":"simpl.types.collection.ArrayList", "simple_name":"ArrayList", "java_type_name":"java.util.ArrayList", "c_sharp_type_name":"List", "objective_c_type_name":"NSMutableArray", "package_name":"java.util", "simpl.id":"792386646"}},{"name":"comment", "tag_name":"comment", "field":"comment", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1530970753"}}]}, "field_descriptor":[{"name":"describedClass", "tag_name":"described_class", "field":"describedClass", "is_generic":"true", "type":"18", "scalar_type":"Class", "xml_hint":"XML_ATTRIBUTE", "field_type":"Class", "generic_parameters_string":"<?>", "declaring_class_descriptor":{"simpl.ref":"1551083435"}},{"name":"describedClassSimpleName", "tag_name":"described_class_simple_name", "field":"describedClassSimpleName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1551083435"}},{"name":"describedClassPackageName", "tag_name":"described_class_package_name", "field":"describedClassPackageName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1551083435"}},{"name":"superClass", "tag_name":"super_class", "field":"superClass", "element_class":"ecologylab.serialization.ClassDescriptor", "type":"3", "composite_tag_name":"super_class", "field_type":"ClassDescriptor", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}},{"name":"interfaces", "tag_name":"interfaces", "field":"interfaces", "is_generic":"true", "type":"5", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"interface", "wrapped":"true", "field_type":"ArrayList", "generic_parameters_string":"<String>", "other_tag":["inerface"], "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "collection_type":{"simpl.ref":"792386646"}},{"name":"declaredFieldDescriptorsByFieldName", "tag_name":"declared_field_descriptors_by_field_name", "field":"declaredFieldDescriptorsByFieldName", "map_key_field_name":"name", "element_class":"ecologylab.serialization.FieldDescriptor", "is_generic":"true", "type":"6", "collection_or_map_tag_name":"field_descriptor", "field_type":"HashMapArrayList", "generic_parameters_string":"<String, ?>", "element_class_descriptor":{"name":"ecologylab.serialization.FieldDescriptor", "tag_name":"field_descriptor", "described_class":"ecologylab.serialization.FieldDescriptor", "described_class_simple_name":"FieldDescriptor", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1893488603", "super_class":{"simpl.ref":"1530970753"}, "field_descriptor":[{"name":"field", "tag_name":"field", "field":"field", "type":"18", "scalar_type":"Field", "xml_hint":"XML_ATTRIBUTE", "field_type":"Field", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"elementClassDescriptor", "tag_name":"element_class_descriptor", "field":"elementClassDescriptor", "element_class":"ecologylab.serialization.ClassDescriptor", "type":"3", "composite_tag_name":"element_class_descriptor", "field_type":"ClassDescriptor", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}},{"name":"mapKeyFieldName", "tag_name":"map_key_field_name", "field":"mapKeyFieldName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"declaringClassDescriptor", "tag_name":"declaring_class_descriptor", "field":"declaringClassDescriptor", "element_class":"ecologylab.serialization.ClassDescriptor", "type":"3", "composite_tag_name":"declaring_class_descriptor", "field_type":"ClassDescriptor", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}},{"name":"elementClass", "tag_name":"element_class", "field":"elementClass", "type":"18", "scalar_type":"Class", "xml_hint":"XML_ATTRIBUTE", "field_type":"Class", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"isGeneric", "tag_name":"is_generic", "field":"isGeneric", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"polymorphClassDescriptors", "tag_name":"polymorph_class_descriptors", "field":"polymorphClassDescriptors", "map_key_field_name":"tagName", "element_class":"ecologylab.serialization.ClassDescriptor", "is_generic":"true", "type":"6", "collection_or_map_tag_name":"polymorph_class_descriptor", "wrapped":"true", "field_type":"HashMapArrayList", "generic_parameters_string":"<String, ClassDescriptor>", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}, "collection_type":{"name":"ecologylab.generic.HashMapArrayList", "simple_name":"HashMapArrayList", "java_type_name":"ecologylab.generic.HashMapArrayList", "c_sharp_type_name":"DictionaryList", "objective_c_type_name":"NSDictionaryList", "package_name":"ecologylab.generic", "is_map":"true", "simpl.id":"1967571412"}},{"name":"polymorphClasses", "tag_name":"polymorph_classes", "field":"polymorphClasses", "is_generic":"true", "type":"7", "scalar_type":"Class", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"polymorph_class", "wrapped":"true", "field_type":"HashMap", "generic_parameters_string":"<String, Class>", "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "collection_type":{"name":"simpl.types.collection.HashMap", "simple_name":"HashMap", "java_type_name":"java.util.HashMap", "c_sharp_type_name":"Dictionary", "objective_c_type_name":"NSDictionary", "package_name":"java.util", "is_map":"true", "simpl.id":"855703640"}},{"name":"libraryNamespaces", "tag_name":"library_namespaces", "field":"libraryNamespaces", "is_generic":"true", "type":"7", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"library_namespace", "wrapped":"true", "field_type":"HashMap", "generic_parameters_string":"<String, String>", "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "collection_type":{"simpl.ref":"855703640"}},{"name":"type", "tag_name":"type", "field":"type", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"scalarType", "tag_name":"scalar_type", "field":"scalarType", "is_generic":"true", "type":"18", "scalar_type":"ScalarType", "xml_hint":"XML_ATTRIBUTE", "field_type":"ScalarType", "generic_parameters_string":"<?>", "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization.types"]}},{"name":"collectionType", "tag_name":"collection_type", "field":"collectionType", "element_class":"ecologylab.serialization.types.CollectionType", "type":"3", "composite_tag_name":"collection_type", "field_type":"CollectionType", "element_class_descriptor":{"name":"ecologylab.serialization.types.CollectionType", "tag_name":"collection_type", "described_class":"ecologylab.serialization.types.CollectionType", "described_class_simple_name":"CollectionType", "described_class_package_name":"ecologylab.serialization.types", "simpl.id":"700804192", "super_class":{"name":"ecologylab.serialization.types.SimplType", "tag_name":"simpl_type", "described_class":"ecologylab.serialization.types.SimplType", "described_class_simple_name":"SimplType", "described_class_package_name":"ecologylab.serialization.types", "simpl.id":"1615734796", "super_class":{"simpl.ref":"2023870964"}, "field_descriptor":[{"name":"simpleName", "tag_name":"simple_name", "field":"simpleName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"javaTypeName", "tag_name":"java_type_name", "field":"javaTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"cSharpTypeName", "tag_name":"c_sharp_type_name", "field":"cSharpTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"objectiveCTypeName", "tag_name":"objective_c_type_name", "field":"objectiveCTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"dbTypeName", "tag_name":"db_type_name", "field":"dbTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"packageName", "tag_name":"package_name", "field":"packageName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}}], "generic_type_variables":{"generic_type_variable":["T"]}}, "field_descriptor":[{"name":"isMap", "tag_name":"is_map", "field":"isMap", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"700804192"}}], "generic_type_variables":{"generic_type_variable":["T"]}}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization.types"]}},{"name":"xmlHint", "tag_name":"xml_hint", "field":"xmlHint", "type":"18", "scalar_type":"Enum", "xml_hint":"XML_ATTRIBUTE", "is_enum":"true", "field_type":"Hint", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"isEnum", "tag_name":"is_enum", "field":"isEnum", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"isCDATA", "tag_name":"is_c_d_a_t_a", "field":"isCDATA", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"needsEscaping", "tag_name":"needs_escaping", "field":"needsEscaping", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"filterRegex", "tag_name":"filter_regex", "field":"filterRegex", "type":"18", "scalar_type":"Pattern", "xml_hint":"XML_ATTRIBUTE", "field_type":"Pattern", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"filterReplace", "tag_name":"filter_replace", "field":"filterReplace", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"unresolvedScopeAnnotation", "tag_name":"unresolved_scope_annotation", "field":"unresolvedScopeAnnotation", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"collectionOrMapTagName", "tag_name":"collection_or_map_tag_name", "field":"collectionOrMapTagName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"compositeTagName", "tag_name":"composite_tag_name", "field":"compositeTagName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"wrapped", "tag_name":"wrapped", "field":"wrapped", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"fieldType", "tag_name":"field_type", "field":"fieldType", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"genericParametersString", "tag_name":"generic_parameters_string", "field":"genericParametersString", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}}]}, "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "collection_type":{"simpl.ref":"1967571412"}},{"name":"genericTypeVariables", "tag_name":"generic_type_variables", "field":"genericTypeVariables", "is_generic":"true", "type":"5", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"generic_type_variable", "wrapped":"true", "field_type":"ArrayList", "generic_parameters_string":"<String>", "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "collection_type":{"simpl.ref":"792386646"}},{"name":"strictObjectGraphRequired", "tag_name":"strict_object_graph_required", "field":"strictObjectGraphRequired", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1551083435"}}], "generic_type_variables":{"generic_type_variable":["ES","FD"]}}}'; - this._simpl_collection_types = {}; - this._simpl_map_types = {"field_descriptor":"field_descriptor"}; - this._simpl_map_types_keys = {"field_descriptor":"name"}; - this._simpl_composite_types = {"super_class":"class_descriptor"}; - if(json) - { - jsonConstruct(json,this); - return; - } - else - { - if(name) this.name = name; - if(tag_name) this.tag_name = tag_name; - if(other_tags) this.other_tags = other_tags; - if(comment) this.comment = comment; - if(described_class) this.described_class = described_class; - if(described_class_simple_name) this.described_class_simple_name = described_class_simple_name; - if(described_class_package_name) this.described_class_package_name = described_class_package_name; - if(super_class) this.super_class = super_class; - if(interfaces) this.interfaces = interfaces; - if(field_descriptor) this.field_descriptor = field_descriptor; - if(generic_type_variables) this.generic_type_variables = generic_type_variables; - if(strict_object_graph_required) this.strict_object_graph_required = strict_object_graph_required; - } -} - - -function item(json,price,owner_name,name) -{ - this._simpl_object_name = "item"; - this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Item", "tag_name":"item", "described_class":"ecologylab.translators.javascript.test.Item", "described_class_simple_name":"Item", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"27832", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"price", "tag_name":"price", "field":"price", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"27832"}},{"name":"ownerName", "tag_name":"owner_name", "field":"ownerName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"27832"}},{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"27832"}}]}}'; - this._simpl_collection_types = {}; - this._simpl_map_types = {}; - this._simpl_map_types_keys = {}; - this._simpl_composite_types = {}; - if(json) - { - jsonConstruct(json,this); - return; - } - else - { - if(price) this.price = price; - if(owner_name) this.owner_name = owner_name; - if(name) this.name = name; - } -} - - -function player(json,name,strength,speed,skin) -{ - this._simpl_object_name = "player"; - this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Player", "tag_name":"player", "described_class":"ecologylab.translators.javascript.test.Player", "described_class_simple_name":"Player", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"2099705691", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"strength", "tag_name":"strength", "field":"strength", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"speed", "tag_name":"speed", "field":"speed", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"skin", "tag_name":"skin", "field":"skin", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}}]}}'; - this._simpl_collection_types = {}; - this._simpl_map_types = {}; - this._simpl_map_types_keys = {}; - this._simpl_composite_types = {}; - if(json) - { - jsonConstruct(json,this); - return; - } - else - { - if(name) this.name = name; - if(strength) this.strength = strength; - if(speed) this.speed = speed; - if(skin) this.skin = skin; - } -} - - -function human(json,name,strength,speed,skin,rank,level,cash) -{ - this._simpl_object_name = "human"; - this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Human", "tag_name":"human", "described_class":"ecologylab.translators.javascript.test.Human", "described_class_simple_name":"Human", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"800323830", "super_class":{"name":"ecologylab.translators.javascript.test.Player", "tag_name":"player", "described_class":"ecologylab.translators.javascript.test.Player", "described_class_simple_name":"Player", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"2099705691", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"strength", "tag_name":"strength", "field":"strength", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"speed", "tag_name":"speed", "field":"speed", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"skin", "tag_name":"skin", "field":"skin", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}}]}, "field_descriptor":[{"name":"rank", "tag_name":"rank", "field":"rank", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"800323830"}},{"name":"level", "tag_name":"level", "field":"level", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"800323830"}},{"name":"cash", "tag_name":"cash", "field":"cash", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"800323830"}}]}}'; - this._simpl_collection_types = {}; - this._simpl_map_types = {}; - this._simpl_map_types_keys = {}; - this._simpl_composite_types = {}; - if(json) - { - jsonConstruct(json,this); - return; - } - else - { - if(name) this.name = name; - if(strength) this.strength = strength; - if(speed) this.speed = speed; - if(skin) this.skin = skin; - if(rank) this.rank = rank; - if(level) this.level = level; - if(cash) this.cash = cash; - } -} - - -function movements(json,time,moves) -{ - this._simpl_object_name = "movements"; - this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Movements", "tag_name":"movements", "described_class":"ecologylab.translators.javascript.test.Movements", "described_class_simple_name":"Movements", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"1873805543", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1205807115"}, "field_descriptor":[{"name":"time", "tag_name":"time", "field":"time", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"1873805543"}},{"name":"moves", "tag_name":"moves", "field":"moves", "element_class":"ecologylab.translators.javascript.test.Move", "is_generic":"true", "type":"4", "collection_or_map_tag_name":"moves", "field_type":"ArrayList", "generic_parameters_string":"<Move>", "element_class_descriptor":{"name":"ecologylab.translators.javascript.test.Move", "tag_name":"move", "described_class":"ecologylab.translators.javascript.test.Move", "described_class_simple_name":"Move", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"105987312", "super_class":{"simpl.ref":"1205807115"}, "field_descriptor":[{"name":"x", "tag_name":"x", "field":"x", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"y", "tag_name":"y", "field":"y", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"sneaking", "tag_name":"sneaking", "field":"sneaking", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"defending", "tag_name":"defending", "field":"defending", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"moveTime", "tag_name":"move_time", "field":"moveTime", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"105987312"}}]}, "declaring_class_descriptor":{"simpl.ref":"1873805543"}, "library_namespaces":{"library_namespace":["ecologylab.translators.javascript.test"]}, "collection_type":{"name":"simpl.types.collection.ArrayList", "simple_name":"ArrayList", "java_type_name":"java.util.ArrayList", "c_sharp_type_name":"List", "objective_c_type_name":"NSMutableArray", "package_name":"java.util"}}]}}'; - this._simpl_collection_types = {"moves":"move"}; - this._simpl_map_types = {}; - this._simpl_map_types_keys = {}; - this._simpl_composite_types = {}; - if(json) - { - jsonConstruct(json,this); - return; - } - else - { - if(time) this.time = time; - if(moves) this.moves = moves; - } -} - - -function bank(json,items) -{ - this._simpl_object_name = "bank"; - this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Bank", "tag_name":"bank", "described_class":"ecologylab.translators.javascript.test.Bank", "described_class_simple_name":"Bank", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"1281234799", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1205807115"}, "field_descriptor":[{"name":"itemMap", "tag_name":"item_map", "field":"itemMap", "map_key_field_name":"ownerName", "element_class":"ecologylab.translators.javascript.test.Item", "is_generic":"true", "type":"6", "collection_or_map_tag_name":"items", "field_type":"HashMap", "generic_parameters_string":"<String, Item>", "element_class_descriptor":{"name":"ecologylab.translators.javascript.test.Item", "tag_name":"item", "described_class":"ecologylab.translators.javascript.test.Item", "described_class_simple_name":"Item", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"27832", "super_class":{"simpl.ref":"1205807115"}, "field_descriptor":[{"name":"price", "tag_name":"price", "field":"price", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"27832"}},{"name":"ownerName", "tag_name":"owner_name", "field":"ownerName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"27832"}},{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"27832"}}]}, "declaring_class_descriptor":{"simpl.ref":"1281234799"}, "library_namespaces":{"library_namespace":["ecologylab.translators.javascript.test"]}, "collection_type":{"name":"simpl.types.collection.HashMap", "simple_name":"HashMap", "java_type_name":"java.util.HashMap", "c_sharp_type_name":"Dictionary", "objective_c_type_name":"NSDictionary", "package_name":"java.util", "is_map":"true"}}]}}'; - this._simpl_collection_types = {}; - this._simpl_map_types = {"items":"item"}; - this._simpl_map_types_keys = {"items":"owner_name"}; - this._simpl_composite_types = {}; - if(json) - { - jsonConstruct(json,this); - return; - } - else - { - if(items) this.items = items; - } -} - - -function move(json,x,y,sneaking,defending,move_time) -{ - this._simpl_object_name = "move"; - this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Move", "tag_name":"move", "described_class":"ecologylab.translators.javascript.test.Move", "described_class_simple_name":"Move", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"105987312", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"x", "tag_name":"x", "field":"x", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"y", "tag_name":"y", "field":"y", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"sneaking", "tag_name":"sneaking", "field":"sneaking", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"defending", "tag_name":"defending", "field":"defending", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"moveTime", "tag_name":"move_time", "field":"moveTime", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"105987312"}}]}}'; - this._simpl_collection_types = {}; - this._simpl_map_types = {}; - this._simpl_map_types_keys = {}; - this._simpl_composite_types = {}; - if(json) - { - jsonConstruct(json,this); - return; - } - else - { - if(x) this.x = x; - if(y) this.y = y; - if(sneaking) this.sneaking = sneaking; - if(defending) this.defending = defending; - if(move_time) this.move_time = move_time; - } -} - - -function refer_to_self(json,some_data,reference_to_self) -{ - this._simpl_object_name = "refer_to_self"; - this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.ReferToSelf", "tag_name":"refer_to_self", "described_class":"ecologylab.translators.javascript.test.ReferToSelf", "described_class_simple_name":"ReferToSelf", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"1186515174", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"someData", "tag_name":"some_data", "field":"someData", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1186515174"}},{"name":"referenceToSelf", "tag_name":"reference_to_self", "field":"referenceToSelf", "element_class":"ecologylab.translators.javascript.test.ReferToSelf", "type":"3", "composite_tag_name":"reference_to_self", "field_type":"ReferToSelf", "element_class_descriptor":{"simpl.ref":"1186515174"}, "declaring_class_descriptor":{"simpl.ref":"1186515174"}, "library_namespaces":{"library_namespace":["ecologylab.translators.javascript.test"]}}]}}'; - this._simpl_collection_types = {}; - this._simpl_map_types = {}; - this._simpl_map_types_keys = {}; - this._simpl_composite_types = {"reference_to_self":"refer_to_self"}; - if(json) - { - jsonConstruct(json,this); - return; - } - else - { - if(some_data) this.some_data = some_data; - if(reference_to_self) this.reference_to_self = reference_to_self; - } -} - - -function computer(json,name,strength,speed,skin,difficulty,type,ai) -{ - this._simpl_object_name = "computer"; - this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Computer", "tag_name":"computer", "described_class":"ecologylab.translators.javascript.test.Computer", "described_class_simple_name":"Computer", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"729212242", "super_class":{"name":"ecologylab.translators.javascript.test.Player", "tag_name":"player", "described_class":"ecologylab.translators.javascript.test.Player", "described_class_simple_name":"Player", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"2099705691", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"strength", "tag_name":"strength", "field":"strength", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"speed", "tag_name":"speed", "field":"speed", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"skin", "tag_name":"skin", "field":"skin", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}}]}, "field_descriptor":[{"name":"difficulty", "tag_name":"difficulty", "field":"difficulty", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"729212242"}},{"name":"type", "tag_name":"type", "field":"type", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"729212242"}},{"name":"ai", "tag_name":"ai", "field":"ai", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"729212242"}}]}}'; - this._simpl_collection_types = {}; - this._simpl_map_types = {}; - this._simpl_map_types_keys = {}; - this._simpl_composite_types = {}; - if(json) - { - jsonConstruct(json,this); - return; - } - else - { - if(name) this.name = name; - if(strength) this.strength = strength; - if(speed) this.speed = speed; - if(skin) this.skin = skin; - if(difficulty) this.difficulty = difficulty; - if(type) this.type = type; - if(ai) this.ai = ai; - } -} - + +function field_descriptor(json,name,tag_name,other_tags,comment,field,element_class_descriptor,map_key_field_name,declaring_class_descriptor,element_class,is_generic,polymorph_class_descriptors,polymorph_classes,library_namespaces,type,scalar_type,collection_type,xml_hint,is_enum,is_c_d_a_t_a,needs_escaping,filter_regex,filter_replace,unresolved_scope_annotation,collection_or_map_tag_name,composite_tag_name,wrapped,field_type,generic_parameters_string) +{ + this._simpl_object_name = "field_descriptor"; + this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.serialization.FieldDescriptor", "tag_name":"field_descriptor", "described_class":"ecologylab.serialization.FieldDescriptor", "described_class_simple_name":"FieldDescriptor", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1893488603", "super_class":{"name":"ecologylab.serialization.DescriptorBase", "tag_name":"descriptor_base", "described_class":"ecologylab.serialization.DescriptorBase", "described_class_simple_name":"DescriptorBase", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1530970753", "super_class":{"name":"ecologylab.serialization.types.SimplBaseType", "tag_name":"simpl_base_type", "described_class":"ecologylab.serialization.types.SimplBaseType", "described_class_simple_name":"SimplBaseType", "described_class_package_name":"ecologylab.serialization.types", "simpl.id":"2023870964", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "other_tag":["field_name","described_class_name"], "declaring_class_descriptor":{"simpl.ref":"2023870964"}}]}, "field_descriptor":[{"name":"tagName", "tag_name":"tag_name", "field":"tagName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1530970753"}},{"name":"otherTags", "tag_name":"other_tags", "field":"otherTags", "is_generic":"true", "type":"5", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"other_tag", "field_type":"ArrayList", "generic_parameters_string":"<String>", "declaring_class_descriptor":{"simpl.ref":"1530970753"}, "collection_type":{"name":"simpl.types.collection.ArrayList", "simple_name":"ArrayList", "java_type_name":"java.util.ArrayList", "c_sharp_type_name":"List", "objective_c_type_name":"NSMutableArray", "package_name":"java.util", "simpl.id":"792386646"}},{"name":"comment", "tag_name":"comment", "field":"comment", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1530970753"}}]}, "field_descriptor":[{"name":"field", "tag_name":"field", "field":"field", "type":"18", "scalar_type":"Field", "xml_hint":"XML_ATTRIBUTE", "field_type":"Field", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"elementClassDescriptor", "tag_name":"element_class_descriptor", "field":"elementClassDescriptor", "element_class":"ecologylab.serialization.ClassDescriptor", "type":"3", "composite_tag_name":"element_class_descriptor", "field_type":"ClassDescriptor", "element_class_descriptor":{"name":"ecologylab.serialization.ClassDescriptor", "tag_name":"class_descriptor", "described_class":"ecologylab.serialization.ClassDescriptor", "described_class_simple_name":"ClassDescriptor", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1551083435", "super_class":{"simpl.ref":"1530970753"}, "field_descriptor":[{"name":"describedClass", "tag_name":"described_class", "field":"describedClass", "is_generic":"true", "type":"18", "scalar_type":"Class", "xml_hint":"XML_ATTRIBUTE", "field_type":"Class", "generic_parameters_string":"<?>", "declaring_class_descriptor":{"simpl.ref":"1551083435"}},{"name":"describedClassSimpleName", "tag_name":"described_class_simple_name", "field":"describedClassSimpleName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1551083435"}},{"name":"describedClassPackageName", "tag_name":"described_class_package_name", "field":"describedClassPackageName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1551083435"}},{"name":"superClass", "tag_name":"super_class", "field":"superClass", "element_class":"ecologylab.serialization.ClassDescriptor", "type":"3", "composite_tag_name":"super_class", "field_type":"ClassDescriptor", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}},{"name":"interfaces", "tag_name":"interfaces", "field":"interfaces", "is_generic":"true", "type":"5", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"interface", "wrapped":"true", "field_type":"ArrayList", "generic_parameters_string":"<String>", "other_tag":["inerface"], "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "collection_type":{"simpl.ref":"792386646"}},{"name":"declaredFieldDescriptorsByFieldName", "tag_name":"declared_field_descriptors_by_field_name", "field":"declaredFieldDescriptorsByFieldName", "map_key_field_name":"name", "element_class":"ecologylab.serialization.FieldDescriptor", "is_generic":"true", "type":"6", "collection_or_map_tag_name":"field_descriptor", "field_type":"HashMapArrayList", "generic_parameters_string":"<String, ?>", "element_class_descriptor":{"simpl.ref":"1893488603"}, "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "collection_type":{"name":"ecologylab.generic.HashMapArrayList", "simple_name":"HashMapArrayList", "java_type_name":"ecologylab.generic.HashMapArrayList", "c_sharp_type_name":"DictionaryList", "objective_c_type_name":"NSDictionaryList", "package_name":"ecologylab.generic", "is_map":"true", "simpl.id":"1967571412"}},{"name":"genericTypeVariables", "tag_name":"generic_type_variables", "field":"genericTypeVariables", "is_generic":"true", "type":"5", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"generic_type_variable", "wrapped":"true", "field_type":"ArrayList", "generic_parameters_string":"<String>", "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "collection_type":{"simpl.ref":"792386646"}},{"name":"strictObjectGraphRequired", "tag_name":"strict_object_graph_required", "field":"strictObjectGraphRequired", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1551083435"}}], "generic_type_variables":{"generic_type_variable":["ES","FD"]}}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}},{"name":"mapKeyFieldName", "tag_name":"map_key_field_name", "field":"mapKeyFieldName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"declaringClassDescriptor", "tag_name":"declaring_class_descriptor", "field":"declaringClassDescriptor", "element_class":"ecologylab.serialization.ClassDescriptor", "type":"3", "composite_tag_name":"declaring_class_descriptor", "field_type":"ClassDescriptor", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}},{"name":"elementClass", "tag_name":"element_class", "field":"elementClass", "type":"18", "scalar_type":"Class", "xml_hint":"XML_ATTRIBUTE", "field_type":"Class", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"isGeneric", "tag_name":"is_generic", "field":"isGeneric", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"polymorphClassDescriptors", "tag_name":"polymorph_class_descriptors", "field":"polymorphClassDescriptors", "map_key_field_name":"tagName", "element_class":"ecologylab.serialization.ClassDescriptor", "is_generic":"true", "type":"6", "collection_or_map_tag_name":"polymorph_class_descriptor", "wrapped":"true", "field_type":"HashMapArrayList", "generic_parameters_string":"<String, ClassDescriptor>", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}, "collection_type":{"simpl.ref":"1967571412"}},{"name":"polymorphClasses", "tag_name":"polymorph_classes", "field":"polymorphClasses", "is_generic":"true", "type":"7", "scalar_type":"Class", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"polymorph_class", "wrapped":"true", "field_type":"HashMap", "generic_parameters_string":"<String, Class>", "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "collection_type":{"name":"simpl.types.collection.HashMap", "simple_name":"HashMap", "java_type_name":"java.util.HashMap", "c_sharp_type_name":"Dictionary", "objective_c_type_name":"NSDictionary", "package_name":"java.util", "is_map":"true", "simpl.id":"855703640"}},{"name":"libraryNamespaces", "tag_name":"library_namespaces", "field":"libraryNamespaces", "is_generic":"true", "type":"7", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"library_namespace", "wrapped":"true", "field_type":"HashMap", "generic_parameters_string":"<String, String>", "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "collection_type":{"simpl.ref":"855703640"}},{"name":"type", "tag_name":"type", "field":"type", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"scalarType", "tag_name":"scalar_type", "field":"scalarType", "is_generic":"true", "type":"18", "scalar_type":"ScalarType", "xml_hint":"XML_ATTRIBUTE", "field_type":"ScalarType", "generic_parameters_string":"<?>", "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization.types"]}},{"name":"collectionType", "tag_name":"collection_type", "field":"collectionType", "element_class":"ecologylab.serialization.types.CollectionType", "type":"3", "composite_tag_name":"collection_type", "field_type":"CollectionType", "element_class_descriptor":{"name":"ecologylab.serialization.types.CollectionType", "tag_name":"collection_type", "described_class":"ecologylab.serialization.types.CollectionType", "described_class_simple_name":"CollectionType", "described_class_package_name":"ecologylab.serialization.types", "simpl.id":"700804192", "super_class":{"name":"ecologylab.serialization.types.SimplType", "tag_name":"simpl_type", "described_class":"ecologylab.serialization.types.SimplType", "described_class_simple_name":"SimplType", "described_class_package_name":"ecologylab.serialization.types", "simpl.id":"1615734796", "super_class":{"simpl.ref":"2023870964"}, "field_descriptor":[{"name":"simpleName", "tag_name":"simple_name", "field":"simpleName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"javaTypeName", "tag_name":"java_type_name", "field":"javaTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"cSharpTypeName", "tag_name":"c_sharp_type_name", "field":"cSharpTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"objectiveCTypeName", "tag_name":"objective_c_type_name", "field":"objectiveCTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"dbTypeName", "tag_name":"db_type_name", "field":"dbTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"packageName", "tag_name":"package_name", "field":"packageName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}}], "generic_type_variables":{"generic_type_variable":["T"]}}, "field_descriptor":[{"name":"isMap", "tag_name":"is_map", "field":"isMap", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"700804192"}}], "generic_type_variables":{"generic_type_variable":["T"]}}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization.types"]}},{"name":"xmlHint", "tag_name":"xml_hint", "field":"xmlHint", "type":"18", "scalar_type":"Enum", "xml_hint":"XML_ATTRIBUTE", "is_enum":"true", "field_type":"Hint", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"isEnum", "tag_name":"is_enum", "field":"isEnum", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"isCDATA", "tag_name":"is_c_d_a_t_a", "field":"isCDATA", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"needsEscaping", "tag_name":"needs_escaping", "field":"needsEscaping", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"filterRegex", "tag_name":"filter_regex", "field":"filterRegex", "type":"18", "scalar_type":"Pattern", "xml_hint":"XML_ATTRIBUTE", "field_type":"Pattern", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"filterReplace", "tag_name":"filter_replace", "field":"filterReplace", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"unresolvedScopeAnnotation", "tag_name":"unresolved_scope_annotation", "field":"unresolvedScopeAnnotation", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"collectionOrMapTagName", "tag_name":"collection_or_map_tag_name", "field":"collectionOrMapTagName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"compositeTagName", "tag_name":"composite_tag_name", "field":"compositeTagName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"wrapped", "tag_name":"wrapped", "field":"wrapped", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"fieldType", "tag_name":"field_type", "field":"fieldType", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"genericParametersString", "tag_name":"generic_parameters_string", "field":"genericParametersString", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}}]}}'; + this._simpl_collection_types = {}; + this._simpl_map_types = {"polymorph_class_descriptors":"class_descriptor","polymorph_classes":"object","library_namespaces":"object"}; + this._simpl_map_types_keys = {"polymorph_class_descriptors":"tag_name","polymorph_classes":"object","library_namespaces":"object"}; + this._simpl_composite_types = {"element_class_descriptor":"class_descriptor","declaring_class_descriptor":"class_descriptor","collection_type":"collection_type"}; + if(json) + { + jsonConstruct(json,this); + return; + } + else + { + if(name) this.name = name; + if(tag_name) this.tag_name = tag_name; + if(other_tags) this.other_tags = other_tags; + if(comment) this.comment = comment; + if(field) this.field = field; + if(element_class_descriptor) this.element_class_descriptor = element_class_descriptor; + if(map_key_field_name) this.map_key_field_name = map_key_field_name; + if(declaring_class_descriptor) this.declaring_class_descriptor = declaring_class_descriptor; + if(element_class) this.element_class = element_class; + if(is_generic) this.is_generic = is_generic; + if(polymorph_class_descriptors) this.polymorph_class_descriptors = polymorph_class_descriptors; + if(polymorph_classes) this.polymorph_classes = polymorph_classes; + if(library_namespaces) this.library_namespaces = library_namespaces; + if(type) this.type = type; + if(scalar_type) this.scalar_type = scalar_type; + if(collection_type) this.collection_type = collection_type; + if(xml_hint) this.xml_hint = xml_hint; + if(is_enum) this.is_enum = is_enum; + if(is_c_d_a_t_a) this.is_c_d_a_t_a = is_c_d_a_t_a; + if(needs_escaping) this.needs_escaping = needs_escaping; + if(filter_regex) this.filter_regex = filter_regex; + if(filter_replace) this.filter_replace = filter_replace; + if(unresolved_scope_annotation) this.unresolved_scope_annotation = unresolved_scope_annotation; + if(collection_or_map_tag_name) this.collection_or_map_tag_name = collection_or_map_tag_name; + if(composite_tag_name) this.composite_tag_name = composite_tag_name; + if(wrapped) this.wrapped = wrapped; + if(field_type) this.field_type = field_type; + if(generic_parameters_string) this.generic_parameters_string = generic_parameters_string; + } +} + + +function class_descriptor(json,name,tag_name,other_tags,comment,described_class,described_class_simple_name,described_class_package_name,super_class,interfaces,field_descriptor,generic_type_variables,strict_object_graph_required) +{ + this._simpl_object_name = "class_descriptor"; + this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.serialization.ClassDescriptor", "tag_name":"class_descriptor", "described_class":"ecologylab.serialization.ClassDescriptor", "described_class_simple_name":"ClassDescriptor", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1551083435", "super_class":{"name":"ecologylab.serialization.DescriptorBase", "tag_name":"descriptor_base", "described_class":"ecologylab.serialization.DescriptorBase", "described_class_simple_name":"DescriptorBase", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1530970753", "super_class":{"name":"ecologylab.serialization.types.SimplBaseType", "tag_name":"simpl_base_type", "described_class":"ecologylab.serialization.types.SimplBaseType", "described_class_simple_name":"SimplBaseType", "described_class_package_name":"ecologylab.serialization.types", "simpl.id":"2023870964", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "other_tag":["field_name","described_class_name"], "declaring_class_descriptor":{"simpl.ref":"2023870964"}}]}, "field_descriptor":[{"name":"tagName", "tag_name":"tag_name", "field":"tagName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1530970753"}},{"name":"otherTags", "tag_name":"other_tags", "field":"otherTags", "is_generic":"true", "type":"5", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"other_tag", "field_type":"ArrayList", "generic_parameters_string":"<String>", "declaring_class_descriptor":{"simpl.ref":"1530970753"}, "collection_type":{"name":"simpl.types.collection.ArrayList", "simple_name":"ArrayList", "java_type_name":"java.util.ArrayList", "c_sharp_type_name":"List", "objective_c_type_name":"NSMutableArray", "package_name":"java.util", "simpl.id":"792386646"}},{"name":"comment", "tag_name":"comment", "field":"comment", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1530970753"}}]}, "field_descriptor":[{"name":"describedClass", "tag_name":"described_class", "field":"describedClass", "is_generic":"true", "type":"18", "scalar_type":"Class", "xml_hint":"XML_ATTRIBUTE", "field_type":"Class", "generic_parameters_string":"<?>", "declaring_class_descriptor":{"simpl.ref":"1551083435"}},{"name":"describedClassSimpleName", "tag_name":"described_class_simple_name", "field":"describedClassSimpleName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1551083435"}},{"name":"describedClassPackageName", "tag_name":"described_class_package_name", "field":"describedClassPackageName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1551083435"}},{"name":"superClass", "tag_name":"super_class", "field":"superClass", "element_class":"ecologylab.serialization.ClassDescriptor", "type":"3", "composite_tag_name":"super_class", "field_type":"ClassDescriptor", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}},{"name":"interfaces", "tag_name":"interfaces", "field":"interfaces", "is_generic":"true", "type":"5", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"interface", "wrapped":"true", "field_type":"ArrayList", "generic_parameters_string":"<String>", "other_tag":["inerface"], "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "collection_type":{"simpl.ref":"792386646"}},{"name":"declaredFieldDescriptorsByFieldName", "tag_name":"declared_field_descriptors_by_field_name", "field":"declaredFieldDescriptorsByFieldName", "map_key_field_name":"name", "element_class":"ecologylab.serialization.FieldDescriptor", "is_generic":"true", "type":"6", "collection_or_map_tag_name":"field_descriptor", "field_type":"HashMapArrayList", "generic_parameters_string":"<String, ?>", "element_class_descriptor":{"name":"ecologylab.serialization.FieldDescriptor", "tag_name":"field_descriptor", "described_class":"ecologylab.serialization.FieldDescriptor", "described_class_simple_name":"FieldDescriptor", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1893488603", "super_class":{"simpl.ref":"1530970753"}, "field_descriptor":[{"name":"field", "tag_name":"field", "field":"field", "type":"18", "scalar_type":"Field", "xml_hint":"XML_ATTRIBUTE", "field_type":"Field", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"elementClassDescriptor", "tag_name":"element_class_descriptor", "field":"elementClassDescriptor", "element_class":"ecologylab.serialization.ClassDescriptor", "type":"3", "composite_tag_name":"element_class_descriptor", "field_type":"ClassDescriptor", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}},{"name":"mapKeyFieldName", "tag_name":"map_key_field_name", "field":"mapKeyFieldName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"declaringClassDescriptor", "tag_name":"declaring_class_descriptor", "field":"declaringClassDescriptor", "element_class":"ecologylab.serialization.ClassDescriptor", "type":"3", "composite_tag_name":"declaring_class_descriptor", "field_type":"ClassDescriptor", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}},{"name":"elementClass", "tag_name":"element_class", "field":"elementClass", "type":"18", "scalar_type":"Class", "xml_hint":"XML_ATTRIBUTE", "field_type":"Class", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"isGeneric", "tag_name":"is_generic", "field":"isGeneric", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"polymorphClassDescriptors", "tag_name":"polymorph_class_descriptors", "field":"polymorphClassDescriptors", "map_key_field_name":"tagName", "element_class":"ecologylab.serialization.ClassDescriptor", "is_generic":"true", "type":"6", "collection_or_map_tag_name":"polymorph_class_descriptor", "wrapped":"true", "field_type":"HashMapArrayList", "generic_parameters_string":"<String, ClassDescriptor>", "element_class_descriptor":{"simpl.ref":"1551083435"}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization"]}, "collection_type":{"name":"ecologylab.generic.HashMapArrayList", "simple_name":"HashMapArrayList", "java_type_name":"ecologylab.generic.HashMapArrayList", "c_sharp_type_name":"DictionaryList", "objective_c_type_name":"NSDictionaryList", "package_name":"ecologylab.generic", "is_map":"true", "simpl.id":"1967571412"}},{"name":"polymorphClasses", "tag_name":"polymorph_classes", "field":"polymorphClasses", "is_generic":"true", "type":"7", "scalar_type":"Class", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"polymorph_class", "wrapped":"true", "field_type":"HashMap", "generic_parameters_string":"<String, Class>", "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "collection_type":{"name":"simpl.types.collection.HashMap", "simple_name":"HashMap", "java_type_name":"java.util.HashMap", "c_sharp_type_name":"Dictionary", "objective_c_type_name":"NSDictionary", "package_name":"java.util", "is_map":"true", "simpl.id":"855703640"}},{"name":"libraryNamespaces", "tag_name":"library_namespaces", "field":"libraryNamespaces", "is_generic":"true", "type":"7", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"library_namespace", "wrapped":"true", "field_type":"HashMap", "generic_parameters_string":"<String, String>", "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "collection_type":{"simpl.ref":"855703640"}},{"name":"type", "tag_name":"type", "field":"type", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"scalarType", "tag_name":"scalar_type", "field":"scalarType", "is_generic":"true", "type":"18", "scalar_type":"ScalarType", "xml_hint":"XML_ATTRIBUTE", "field_type":"ScalarType", "generic_parameters_string":"<?>", "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization.types"]}},{"name":"collectionType", "tag_name":"collection_type", "field":"collectionType", "element_class":"ecologylab.serialization.types.CollectionType", "type":"3", "composite_tag_name":"collection_type", "field_type":"CollectionType", "element_class_descriptor":{"name":"ecologylab.serialization.types.CollectionType", "tag_name":"collection_type", "described_class":"ecologylab.serialization.types.CollectionType", "described_class_simple_name":"CollectionType", "described_class_package_name":"ecologylab.serialization.types", "simpl.id":"700804192", "super_class":{"name":"ecologylab.serialization.types.SimplType", "tag_name":"simpl_type", "described_class":"ecologylab.serialization.types.SimplType", "described_class_simple_name":"SimplType", "described_class_package_name":"ecologylab.serialization.types", "simpl.id":"1615734796", "super_class":{"simpl.ref":"2023870964"}, "field_descriptor":[{"name":"simpleName", "tag_name":"simple_name", "field":"simpleName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"javaTypeName", "tag_name":"java_type_name", "field":"javaTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"cSharpTypeName", "tag_name":"c_sharp_type_name", "field":"cSharpTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"objectiveCTypeName", "tag_name":"objective_c_type_name", "field":"objectiveCTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"dbTypeName", "tag_name":"db_type_name", "field":"dbTypeName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}},{"name":"packageName", "tag_name":"package_name", "field":"packageName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1615734796"}}], "generic_type_variables":{"generic_type_variable":["T"]}}, "field_descriptor":[{"name":"isMap", "tag_name":"is_map", "field":"isMap", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"700804192"}}], "generic_type_variables":{"generic_type_variable":["T"]}}, "declaring_class_descriptor":{"simpl.ref":"1893488603"}, "library_namespaces":{"library_namespace":["ecologylab.serialization.types"]}},{"name":"xmlHint", "tag_name":"xml_hint", "field":"xmlHint", "type":"18", "scalar_type":"Enum", "xml_hint":"XML_ATTRIBUTE", "is_enum":"true", "field_type":"Hint", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"isEnum", "tag_name":"is_enum", "field":"isEnum", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"isCDATA", "tag_name":"is_c_d_a_t_a", "field":"isCDATA", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"needsEscaping", "tag_name":"needs_escaping", "field":"needsEscaping", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"filterRegex", "tag_name":"filter_regex", "field":"filterRegex", "type":"18", "scalar_type":"Pattern", "xml_hint":"XML_ATTRIBUTE", "field_type":"Pattern", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"filterReplace", "tag_name":"filter_replace", "field":"filterReplace", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"unresolvedScopeAnnotation", "tag_name":"unresolved_scope_annotation", "field":"unresolvedScopeAnnotation", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"collectionOrMapTagName", "tag_name":"collection_or_map_tag_name", "field":"collectionOrMapTagName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"compositeTagName", "tag_name":"composite_tag_name", "field":"compositeTagName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"wrapped", "tag_name":"wrapped", "field":"wrapped", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"fieldType", "tag_name":"field_type", "field":"fieldType", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}},{"name":"genericParametersString", "tag_name":"generic_parameters_string", "field":"genericParametersString", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1893488603"}}]}, "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "collection_type":{"simpl.ref":"1967571412"}},{"name":"genericTypeVariables", "tag_name":"generic_type_variables", "field":"genericTypeVariables", "is_generic":"true", "type":"5", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "collection_or_map_tag_name":"generic_type_variable", "wrapped":"true", "field_type":"ArrayList", "generic_parameters_string":"<String>", "declaring_class_descriptor":{"simpl.ref":"1551083435"}, "collection_type":{"simpl.ref":"792386646"}},{"name":"strictObjectGraphRequired", "tag_name":"strict_object_graph_required", "field":"strictObjectGraphRequired", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"1551083435"}}], "generic_type_variables":{"generic_type_variable":["ES","FD"]}}}'; + this._simpl_collection_types = {}; + this._simpl_map_types = {"field_descriptor":"field_descriptor"}; + this._simpl_map_types_keys = {"field_descriptor":"name"}; + this._simpl_composite_types = {"super_class":"class_descriptor"}; + if(json) + { + jsonConstruct(json,this); + return; + } + else + { + if(name) this.name = name; + if(tag_name) this.tag_name = tag_name; + if(other_tags) this.other_tags = other_tags; + if(comment) this.comment = comment; + if(described_class) this.described_class = described_class; + if(described_class_simple_name) this.described_class_simple_name = described_class_simple_name; + if(described_class_package_name) this.described_class_package_name = described_class_package_name; + if(super_class) this.super_class = super_class; + if(interfaces) this.interfaces = interfaces; + if(field_descriptor) this.field_descriptor = field_descriptor; + if(generic_type_variables) this.generic_type_variables = generic_type_variables; + if(strict_object_graph_required) this.strict_object_graph_required = strict_object_graph_required; + } +} + + +function item(json,price,owner_name,name) +{ + this._simpl_object_name = "item"; + this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Item", "tag_name":"item", "described_class":"ecologylab.translators.javascript.test.Item", "described_class_simple_name":"Item", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"27832", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"price", "tag_name":"price", "field":"price", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"27832"}},{"name":"ownerName", "tag_name":"owner_name", "field":"ownerName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"27832"}},{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"27832"}}]}}'; + this._simpl_collection_types = {}; + this._simpl_map_types = {}; + this._simpl_map_types_keys = {}; + this._simpl_composite_types = {}; + if(json) + { + jsonConstruct(json,this); + return; + } + else + { + if(price) this.price = price; + if(owner_name) this.owner_name = owner_name; + if(name) this.name = name; + } +} + + +function player(json,name,strength,speed,skin) +{ + this._simpl_object_name = "player"; + this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Player", "tag_name":"player", "described_class":"ecologylab.translators.javascript.test.Player", "described_class_simple_name":"Player", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"2099705691", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"strength", "tag_name":"strength", "field":"strength", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"speed", "tag_name":"speed", "field":"speed", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"skin", "tag_name":"skin", "field":"skin", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}}]}}'; + this._simpl_collection_types = {}; + this._simpl_map_types = {}; + this._simpl_map_types_keys = {}; + this._simpl_composite_types = {}; + if(json) + { + jsonConstruct(json,this); + return; + } + else + { + if(name) this.name = name; + if(strength) this.strength = strength; + if(speed) this.speed = speed; + if(skin) this.skin = skin; + } +} + + +function human(json,name,strength,speed,skin,rank,level,cash) +{ + this._simpl_object_name = "human"; + this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Human", "tag_name":"human", "described_class":"ecologylab.translators.javascript.test.Human", "described_class_simple_name":"Human", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"800323830", "super_class":{"name":"ecologylab.translators.javascript.test.Player", "tag_name":"player", "described_class":"ecologylab.translators.javascript.test.Player", "described_class_simple_name":"Player", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"2099705691", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"strength", "tag_name":"strength", "field":"strength", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"speed", "tag_name":"speed", "field":"speed", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"skin", "tag_name":"skin", "field":"skin", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}}]}, "field_descriptor":[{"name":"rank", "tag_name":"rank", "field":"rank", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"800323830"}},{"name":"level", "tag_name":"level", "field":"level", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"800323830"}},{"name":"cash", "tag_name":"cash", "field":"cash", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"800323830"}}]}}'; + this._simpl_collection_types = {}; + this._simpl_map_types = {}; + this._simpl_map_types_keys = {}; + this._simpl_composite_types = {}; + if(json) + { + jsonConstruct(json,this); + return; + } + else + { + if(name) this.name = name; + if(strength) this.strength = strength; + if(speed) this.speed = speed; + if(skin) this.skin = skin; + if(rank) this.rank = rank; + if(level) this.level = level; + if(cash) this.cash = cash; + } +} + + +function movements(json,time,moves) +{ + this._simpl_object_name = "movements"; + this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Movements", "tag_name":"movements", "described_class":"ecologylab.translators.javascript.test.Movements", "described_class_simple_name":"Movements", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"1873805543", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1205807115"}, "field_descriptor":[{"name":"time", "tag_name":"time", "field":"time", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"1873805543"}},{"name":"moves", "tag_name":"moves", "field":"moves", "element_class":"ecologylab.translators.javascript.test.Move", "is_generic":"true", "type":"4", "collection_or_map_tag_name":"moves", "field_type":"ArrayList", "generic_parameters_string":"<Move>", "element_class_descriptor":{"name":"ecologylab.translators.javascript.test.Move", "tag_name":"move", "described_class":"ecologylab.translators.javascript.test.Move", "described_class_simple_name":"Move", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"105987312", "super_class":{"simpl.ref":"1205807115"}, "field_descriptor":[{"name":"x", "tag_name":"x", "field":"x", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"y", "tag_name":"y", "field":"y", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"sneaking", "tag_name":"sneaking", "field":"sneaking", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"defending", "tag_name":"defending", "field":"defending", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"moveTime", "tag_name":"move_time", "field":"moveTime", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"105987312"}}]}, "declaring_class_descriptor":{"simpl.ref":"1873805543"}, "library_namespaces":{"library_namespace":["ecologylab.translators.javascript.test"]}, "collection_type":{"name":"simpl.types.collection.ArrayList", "simple_name":"ArrayList", "java_type_name":"java.util.ArrayList", "c_sharp_type_name":"List", "objective_c_type_name":"NSMutableArray", "package_name":"java.util"}}]}}'; + this._simpl_collection_types = {"moves":"move"}; + this._simpl_map_types = {}; + this._simpl_map_types_keys = {}; + this._simpl_composite_types = {}; + if(json) + { + jsonConstruct(json,this); + return; + } + else + { + if(time) this.time = time; + if(moves) this.moves = moves; + } +} + + +function bank(json,items) +{ + this._simpl_object_name = "bank"; + this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Bank", "tag_name":"bank", "described_class":"ecologylab.translators.javascript.test.Bank", "described_class_simple_name":"Bank", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"1281234799", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization", "simpl.id":"1205807115"}, "field_descriptor":[{"name":"itemMap", "tag_name":"item_map", "field":"itemMap", "map_key_field_name":"ownerName", "element_class":"ecologylab.translators.javascript.test.Item", "is_generic":"true", "type":"6", "collection_or_map_tag_name":"items", "field_type":"HashMap", "generic_parameters_string":"<String, Item>", "element_class_descriptor":{"name":"ecologylab.translators.javascript.test.Item", "tag_name":"item", "described_class":"ecologylab.translators.javascript.test.Item", "described_class_simple_name":"Item", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"27832", "super_class":{"simpl.ref":"1205807115"}, "field_descriptor":[{"name":"price", "tag_name":"price", "field":"price", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"27832"}},{"name":"ownerName", "tag_name":"owner_name", "field":"ownerName", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"27832"}},{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"27832"}}]}, "declaring_class_descriptor":{"simpl.ref":"1281234799"}, "library_namespaces":{"library_namespace":["ecologylab.translators.javascript.test"]}, "collection_type":{"name":"simpl.types.collection.HashMap", "simple_name":"HashMap", "java_type_name":"java.util.HashMap", "c_sharp_type_name":"Dictionary", "objective_c_type_name":"NSDictionary", "package_name":"java.util", "is_map":"true"}}]}}'; + this._simpl_collection_types = {}; + this._simpl_map_types = {"items":"item"}; + this._simpl_map_types_keys = {"items":"owner_name"}; + this._simpl_composite_types = {}; + if(json) + { + jsonConstruct(json,this); + return; + } + else + { + if(items) this.items = items; + } +} + + +function move(json,x,y,sneaking,defending,move_time) +{ + this._simpl_object_name = "move"; + this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Move", "tag_name":"move", "described_class":"ecologylab.translators.javascript.test.Move", "described_class_simple_name":"Move", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"105987312", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"x", "tag_name":"x", "field":"x", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"y", "tag_name":"y", "field":"y", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"sneaking", "tag_name":"sneaking", "field":"sneaking", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"defending", "tag_name":"defending", "field":"defending", "type":"18", "scalar_type":"boolean", "xml_hint":"XML_ATTRIBUTE", "field_type":"boolean", "declaring_class_descriptor":{"simpl.ref":"105987312"}},{"name":"moveTime", "tag_name":"move_time", "field":"moveTime", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"105987312"}}]}}'; + this._simpl_collection_types = {}; + this._simpl_map_types = {}; + this._simpl_map_types_keys = {}; + this._simpl_composite_types = {}; + if(json) + { + jsonConstruct(json,this); + return; + } + else + { + if(x) this.x = x; + if(y) this.y = y; + if(sneaking) this.sneaking = sneaking; + if(defending) this.defending = defending; + if(move_time) this.move_time = move_time; + } +} + + +function refer_to_self(json,some_data,reference_to_self) +{ + this._simpl_object_name = "refer_to_self"; + this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.ReferToSelf", "tag_name":"refer_to_self", "described_class":"ecologylab.translators.javascript.test.ReferToSelf", "described_class_simple_name":"ReferToSelf", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"1186515174", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"someData", "tag_name":"some_data", "field":"someData", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"1186515174"}},{"name":"referenceToSelf", "tag_name":"reference_to_self", "field":"referenceToSelf", "element_class":"ecologylab.translators.javascript.test.ReferToSelf", "type":"3", "composite_tag_name":"reference_to_self", "field_type":"ReferToSelf", "element_class_descriptor":{"simpl.ref":"1186515174"}, "declaring_class_descriptor":{"simpl.ref":"1186515174"}, "library_namespaces":{"library_namespace":["ecologylab.translators.javascript.test"]}}]}}'; + this._simpl_collection_types = {}; + this._simpl_map_types = {}; + this._simpl_map_types_keys = {}; + this._simpl_composite_types = {"reference_to_self":"refer_to_self"}; + if(json) + { + jsonConstruct(json,this); + return; + } + else + { + if(some_data) this.some_data = some_data; + if(reference_to_self) this.reference_to_self = reference_to_self; + } +} + + +function computer(json,name,strength,speed,skin,difficulty,type,ai) +{ + this._simpl_object_name = "computer"; + this._simpl_class_descriptor='{"class_descriptor":{"name":"ecologylab.translators.javascript.test.Computer", "tag_name":"computer", "described_class":"ecologylab.translators.javascript.test.Computer", "described_class_simple_name":"Computer", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"729212242", "super_class":{"name":"ecologylab.translators.javascript.test.Player", "tag_name":"player", "described_class":"ecologylab.translators.javascript.test.Player", "described_class_simple_name":"Player", "described_class_package_name":"ecologylab.translators.javascript.test", "simpl.id":"2099705691", "super_class":{"name":"ecologylab.serialization.ElementState", "tag_name":"element", "described_class":"ecologylab.serialization.ElementState", "described_class_simple_name":"ElementState", "described_class_package_name":"ecologylab.serialization"}, "field_descriptor":[{"name":"name", "tag_name":"name", "field":"name", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"strength", "tag_name":"strength", "field":"strength", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"speed", "tag_name":"speed", "field":"speed", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}},{"name":"skin", "tag_name":"skin", "field":"skin", "type":"18", "scalar_type":"int", "xml_hint":"XML_ATTRIBUTE", "field_type":"int", "declaring_class_descriptor":{"simpl.ref":"2099705691"}}]}, "field_descriptor":[{"name":"difficulty", "tag_name":"difficulty", "field":"difficulty", "type":"18", "scalar_type":"float", "xml_hint":"XML_ATTRIBUTE", "field_type":"float", "declaring_class_descriptor":{"simpl.ref":"729212242"}},{"name":"type", "tag_name":"type", "field":"type", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"729212242"}},{"name":"ai", "tag_name":"ai", "field":"ai", "type":"18", "scalar_type":"String", "xml_hint":"XML_ATTRIBUTE", "field_type":"String", "declaring_class_descriptor":{"simpl.ref":"729212242"}}]}}'; + this._simpl_collection_types = {}; + this._simpl_map_types = {}; + this._simpl_map_types_keys = {}; + this._simpl_composite_types = {}; + if(json) + { + jsonConstruct(json,this); + return; + } + else + { + if(name) this.name = name; + if(strength) this.strength = strength; + if(speed) this.speed = speed; + if(skin) this.skin = skin; + if(difficulty) this.difficulty = difficulty; + if(type) this.type = type; + if(ai) this.ai = ai; + } +} + diff --git a/simplTranslators/jscode/simpl.js b/simplTranslators/jscode/simpl.js index 5f1c254a..ffc77090 100644 --- a/simplTranslators/jscode/simpl.js +++ b/simplTranslators/jscode/simpl.js @@ -1,476 +1,476 @@ -//simpl.js -//Author Rhema Linder -//Use the methods simplDeserialze and simplSerialze to de/serialze simpl objects. -//simpl objects can be made by using simplTranslator and annotating java code. -///////////////////// - - -var _simpl_ref_index_map = {}; -var _simpl_class_descriptor_map = {}; - - -var _db_almost_never = 3; -var _db_light_warning = 2; -var _db_warning = 1; -var _db_critical_error = 0; - -var _db_level = _db_critical_error;//set to a larger number for more reporting - -//look for firebug var so that you can use alert or something -function console_message(input, level) -{ - if (console.log) { - if(!level) - { - console.log(input); - } - else - { - if(level <= _db_level) - console.log(input); - } - } - else - { - alert("You really really need firebug installed to do debugging."); - } -} - -function addOrGetFromClassDescriptorMap(function_name,descriptor_json) -{ - console_message("addOrGetFromClassDescriptorMap",3); - var returnObject = null; - returnObject = _simpl_class_descriptor_map[function_name]; - if(returnObject) - return returnObject; - if(function_name == "class_descriptor" || function_name == "field_descriptor") - { - returnObject = descriptor_json; - } - else - { - returnObject = simplDeserialize(descriptor_json); - } - _simpl_class_descriptor_map[function_name] = returnObject; - return returnObject; -} - -//This function takes a string that has been deserialized by simpl into json. -function simplDeserialize(json_string) -{ - console_message("simplDeserialize",3); - console_message("simplDeserializeString:"+json_string,3); - var total = 0; - var name = ""; - var uncastObject = json_string; - if(typeof json_string == "string") - uncastObject = eval('('+json_string+')'); - - for(var topLevel in uncastObject) - { - name = topLevel; - console_message("name in top level is...",3); - console_message(name,3); - total+=1; - } - if(total != 1) - { - alert("Error. There should only be 1"+"top level name in this object."); - } - if(name == "object") - { - //alert(JSON.stringify(json_string)); - return json_string['object']; - } - else if(typeof eval(name) != "function") - { - alert("Error. "+name+" is not in your object definitions object."); - } - var contructor = (eval(''+name+'')); - return new contructor(uncastObject[name]); -} - -function no_underscore_replacer(key, value) -{ - if(key == "simpl.id") - { - if(typeof(value) != "string") - { - return undefined; - } - } - if (key[0]=="_") - { - return undefined; - } - else return value; -} - -//Works just like JSON.stringify but ignores any fields with an underscore prefix -function simplStringify(obj) -{ - console_message("simplStringify",3); - return JSON.stringify(obj, no_underscore_replacer); -} - - -//This function is needed to support simpl type maps. -function reformatObject(obj, unwrap) { - console_message("reformatObject",3); - - if(unwrap)//Unwrap puts associative arrays back into Arrays. - { - var k = Array(); - for(var i in obj) - k.push(reformatObject(obj[i])); - return k; - } - var clone = {}; - for(var i in obj) { - if(i[0] == "_") - continue; - var type_inside = null; - if(obj._simpl_map_types) - { - type_inside = obj._simpl_map_types[i]; - } - if(typeof(obj[i])=="object") - { - if(type_inside) - clone[i] = reformatObject(obj[i],true); - else - clone[i] = reformatObject(obj[i]); - } - else - clone[i] = obj[i]; - } - return clone; - } - - -//This serialized object. -function simplSerialize(simpl_object)//we could add something for this... -{ - console_message("simplSerialize",3); - simpl_object = recursivlyGiveEachSimplObjectAnId(simpl_object); - var simpl_object_2 = recursivlyFillReferences(simpl_object); - - var return_object = new Object(); - return_object[""+(simpl_object_2._simpl_object_name)] = simpl_object_2; - return_object = reformatObject(return_object); - simpl_object = cleanAsYouGo(simpl_object); - return simplStringify(return_object); -} - - -//This function makes maps and collections. -function castCollectionOrMap(ownerObject,deserializedCollection,item_key) -{ - console_message("castCollectionOrMap",3); - var top_name = null; - for(var sub in deserializedCollection) - top_name = sub; - var innerItems = deserializedCollection[sub]; - var collection = Array(); - var map = {}; - var innerItemType = ownerObject._simpl_collection_types[top_name]; - var is_map = false; - var is_composite = false; - if(!innerItemType) - { - is_map = true; - innerItemType = ownerObject._simpl_map_types[top_name]; - console_message(top_name,3); - if(!innerItemType) - {//gb probably broked... - console_message("ownerobject is",3); - console_message(ownerObject,3); - console_message("top object don't break is",3); - console_message(top_name,3); - console_message(item_key,3); - var compositeType = ownerObject._simpl_composite_types[top_name]; - if(compositeType) - { - console_message("congrats on finding this composite object",3); - is_composite = true; - } - else if(item_key == "object") - { - console_message("item_key is an object",3); - } - else if(ownerObject[top_name]['simpl.ref']) - { - alert("This is a reference object.");//this probably does not go here... - } - else - { - alert("This should be a map or a collection but it isn't."); - } - - } - } - for(var sub in innerItems) - { - var item = {}; - if(innerItemType)//for collections of composites - item[innerItemType] = innerItems[sub]; - else - item = innerItems[sub]; - { - if(is_composite) - { - console_message("just a composite so I did nothing with",3); - console_message(item,3); - } - else - { - var item = simplDeserialize(item); - if(is_map)//need to check for object type... for which we have a special case of associative arrays that have keys that are the same as their value - { - if(is_map) - { - console_message("Found something to put in this map.. from the item",3); - console_message(item_key,3) - //console_message(item,3);//need to replace stuff here - ownerObject['']; - //map[item[item._map_key]] = item; - map[item[item_key]] = item; - } - } - else - collection.push(item); - } - } - } - if(is_map) - return map; - else - return collection; -} - -//json constuct works as a constructor for simpl objects from json. This is called from simplDeserialize -function jsonConstruct(json,target_object) -{ - console_message("jsonConstruct",3); - target_object['_simpl_class_descriptor'] = addOrGetFromClassDescriptorMap(target_object['_simpl_object_name'],target_object['_simpl_class_descriptor']); - - - for(field in json) - { - console_message("construct field is:"+field,3); - if(typeof json[field] != "object") - { - if(field == "simpl.id") - { - console_message("simpl.id is",3); - console_message(json[field],3); - _simpl_ref_index_map[json[field]] = target_object; - target_object["_simpl_id"] = json[field]; - } - else - { - target_object[field] = json[field]; - } - } - else - { - var collection = {}; - collection[field] = json[field]; - if(collection[field]['simpl.ref']) - { - console_message("wait, we should do something different with this..",3); - console_message(collection[field]['simpl.ref'],3); - console_message("and I hope that was the number",3); - //null may be needed here... - target_object[field] = _simpl_ref_index_map[collection[field]['simpl.ref']]; - } - else - { - console_message("field of the collection or map",3); - console_message(field,3); - var item_key = target_object['_simpl_map_types_keys'][field]; - target_object[field] = castCollectionOrMap(target_object,collection,item_key); - } - } - } - //check on type of class descriptor - //target_object['_simpl_class_descriptor'] = simplDeserialize(target_object['_simpl_class_descriptor']); -} - - -/// -/// -/// -//graph part--------------- -//graphing happens with 2 passes of recursive functions -// -//1. pass, labels everything with a simpl_id -//2. pass, -// -// - -function getNewUnusedId() -{ - var same = 1; - var returnId = 1; - while(same) - { - returnId = ""+Math.floor(Math.random()*100000000); - if(!(returnId in _simpl_ref_index_map)) - same = 0; - } - return returnId; -} - -function isSimplObject(obj) -{ - if(!obj) - return false; - if(typeof(obj) == "object" && '_simpl_object_name' in obj) - return true; - return false; -} - -function cleanAsYouGo(obj, seen_before_things) -{ - if(!seen_before_things) - seen_before_things = {}; - - if(isSimplObject(obj)) - { - if(obj['simpl.id']) - { - if(obj['simpl.id'] in seen_before_things) - { - return obj; - } - seen_before_things[obj['simpl.id']] = 1; - } - } - for(var i in obj) { - //should only be for simpl objects inside of simpl objects but what about collections>>>??? - if(isSimplObject(obj[i])) - cleanAsYouGo(obj[i],seen_before_things); - } - - if(isSimplObject(obj)) - { - obj['simpl.id'] = null; - obj._seen_before = null; - } - return obj; -} - -function cleanupGraphContex(obj) -{ - console_message("cleanupGraphContex",3); - if(isSimplObject(obj)) - { - console_message("this is a simpl object",3); - if('_simpl_crumbs_cleanup' in obj) - { - console_message("simpl crumbs do exist",3); - for(var i=0; i>>??? - if(isSimplObject(obj[i])) - recursivlyGiveEachSimplObjectAnId(obj[i],crumb); - } - return obj; -} - -function recursivlyFillReferences(obj,old_clone) -{ - console_message("recursivlyFillReferences",3); - var clone = {}; - if(old_clone) - clone = old_clone; - for(var i in obj) - { - //if(typeof(obj[i]) == "object") - //{ - // clone[i] = obj[i]; - // console_message(i+" was just an object that should not be done anything with...",3); - - //} - //else - if(isSimplObject(obj[i]))//'_simpl_object_name' in obj[i]) - { - console_message("simpl object found",3); - if('simpl.id' in obj[i]) - { - console_message("simpl.id found in object",3); - if(obj[i]['simpl.id'] in _simpl_ref_index_map) - { - console_message("This object is already made, referencing it",3); - refedObj = {}; - refedNumber = {}; - refedNumber['simpl.ref'] = obj[i]['simpl.id']; - refedObj[obj['_simpl_object_name']] = refedNumber;//old bad - ////refedObj[i] = refedNumber; - clone[i] = refedNumber;//refedObj; - //refedNumber;//no really old - } - else - { - //add to _simpl_ref_index_map - //clone - console_message("This object has not been made. Making it.",3); - _simpl_ref_index_map[obj[i]['simpl.id']] = obj[i]; - clone[i] = obj[i]; - recursivlyFillReferences(obj[i],clone); - } - } - else - { - console_message("Cloneing field " + i + " with teh val "+obj[i],3); - clone[i] = obj[i]; - } - - } - else - { - console_message("Cloneing field " + i + " with teh val "+obj[i],3); - clone[i] = obj[i];//could probably make a better structure for this starement - } - } - return clone; +//simpl.js +//Author Rhema Linder +//Use the methods simplDeserialze and simplSerialze to de/serialze simpl objects. +//simpl objects can be made by using simplTranslator and annotating java code. +///////////////////// + + +var _simpl_ref_index_map = {}; +var _simpl_class_descriptor_map = {}; + + +var _db_almost_never = 3; +var _db_light_warning = 2; +var _db_warning = 1; +var _db_critical_error = 0; + +var _db_level = _db_critical_error;//set to a larger number for more reporting + +//look for firebug var so that you can use alert or something +function console_message(input, level) +{ + if (console.log) { + if(!level) + { + console.log(input); + } + else + { + if(level <= _db_level) + console.log(input); + } + } + else + { + alert("You really really need firebug installed to do debugging."); + } +} + +function addOrGetFromClassDescriptorMap(function_name,descriptor_json) +{ + console_message("addOrGetFromClassDescriptorMap",3); + var returnObject = null; + returnObject = _simpl_class_descriptor_map[function_name]; + if(returnObject) + return returnObject; + if(function_name == "class_descriptor" || function_name == "field_descriptor") + { + returnObject = descriptor_json; + } + else + { + returnObject = simplDeserialize(descriptor_json); + } + _simpl_class_descriptor_map[function_name] = returnObject; + return returnObject; +} + +//This function takes a string that has been deserialized by simpl into json. +function simplDeserialize(json_string) +{ + console_message("simplDeserialize",3); + console_message("simplDeserializeString:"+json_string,3); + var total = 0; + var name = ""; + var uncastObject = json_string; + if(typeof json_string == "string") + uncastObject = eval('('+json_string+')'); + + for(var topLevel in uncastObject) + { + name = topLevel; + console_message("name in top level is...",3); + console_message(name,3); + total+=1; + } + if(total != 1) + { + alert("Error. There should only be 1"+"top level name in this object."); + } + if(name == "object") + { + //alert(JSON.stringify(json_string)); + return json_string['object']; + } + else if(typeof eval(name) != "function") + { + alert("Error. "+name+" is not in your object definitions object."); + } + var contructor = (eval(''+name+'')); + return new contructor(uncastObject[name]); +} + +function no_underscore_replacer(key, value) +{ + if(key == "simpl.id") + { + if(typeof(value) != "string") + { + return undefined; + } + } + if (key[0]=="_") + { + return undefined; + } + else return value; +} + +//Works just like JSON.stringify but ignores any fields with an underscore prefix +function simplStringify(obj) +{ + console_message("simplStringify",3); + return JSON.stringify(obj, no_underscore_replacer); +} + + +//This function is needed to support simpl type maps. +function reformatObject(obj, unwrap) { + console_message("reformatObject",3); + + if(unwrap)//Unwrap puts associative arrays back into Arrays. + { + var k = Array(); + for(var i in obj) + k.push(reformatObject(obj[i])); + return k; + } + var clone = {}; + for(var i in obj) { + if(i[0] == "_") + continue; + var type_inside = null; + if(obj._simpl_map_types) + { + type_inside = obj._simpl_map_types[i]; + } + if(typeof(obj[i])=="object") + { + if(type_inside) + clone[i] = reformatObject(obj[i],true); + else + clone[i] = reformatObject(obj[i]); + } + else + clone[i] = obj[i]; + } + return clone; + } + + +//This serialized object. +function simplSerialize(simpl_object)//we could add something for this... +{ + console_message("simplSerialize",3); + simpl_object = recursivlyGiveEachSimplObjectAnId(simpl_object); + var simpl_object_2 = recursivlyFillReferences(simpl_object); + + var return_object = new Object(); + return_object[""+(simpl_object_2._simpl_object_name)] = simpl_object_2; + return_object = reformatObject(return_object); + simpl_object = cleanAsYouGo(simpl_object); + return simplStringify(return_object); +} + + +//This function makes maps and collections. +function castCollectionOrMap(ownerObject,deserializedCollection,item_key) +{ + console_message("castCollectionOrMap",3); + var top_name = null; + for(var sub in deserializedCollection) + top_name = sub; + var innerItems = deserializedCollection[sub]; + var collection = Array(); + var map = {}; + var innerItemType = ownerObject._simpl_collection_types[top_name]; + var is_map = false; + var is_composite = false; + if(!innerItemType) + { + is_map = true; + innerItemType = ownerObject._simpl_map_types[top_name]; + console_message(top_name,3); + if(!innerItemType) + {//gb probably broked... + console_message("ownerobject is",3); + console_message(ownerObject,3); + console_message("top object don't break is",3); + console_message(top_name,3); + console_message(item_key,3); + var compositeType = ownerObject._simpl_composite_types[top_name]; + if(compositeType) + { + console_message("congrats on finding this composite object",3); + is_composite = true; + } + else if(item_key == "object") + { + console_message("item_key is an object",3); + } + else if(ownerObject[top_name]['simpl.ref']) + { + alert("This is a reference object.");//this probably does not go here... + } + else + { + alert("This should be a map or a collection but it isn't."); + } + + } + } + for(var sub in innerItems) + { + var item = {}; + if(innerItemType)//for collections of composites + item[innerItemType] = innerItems[sub]; + else + item = innerItems[sub]; + { + if(is_composite) + { + console_message("just a composite so I did nothing with",3); + console_message(item,3); + } + else + { + var item = simplDeserialize(item); + if(is_map)//need to check for object type... for which we have a special case of associative arrays that have keys that are the same as their value + { + if(is_map) + { + console_message("Found something to put in this map.. from the item",3); + console_message(item_key,3) + //console_message(item,3);//need to replace stuff here + ownerObject['']; + //map[item[item._map_key]] = item; + map[item[item_key]] = item; + } + } + else + collection.push(item); + } + } + } + if(is_map) + return map; + else + return collection; +} + +//json constuct works as a constructor for simpl objects from json. This is called from simplDeserialize +function jsonConstruct(json,target_object) +{ + console_message("jsonConstruct",3); + target_object['_simpl_class_descriptor'] = addOrGetFromClassDescriptorMap(target_object['_simpl_object_name'],target_object['_simpl_class_descriptor']); + + + for(field in json) + { + console_message("construct field is:"+field,3); + if(typeof json[field] != "object") + { + if(field == "simpl.id") + { + console_message("simpl.id is",3); + console_message(json[field],3); + _simpl_ref_index_map[json[field]] = target_object; + target_object["_simpl_id"] = json[field]; + } + else + { + target_object[field] = json[field]; + } + } + else + { + var collection = {}; + collection[field] = json[field]; + if(collection[field]['simpl.ref']) + { + console_message("wait, we should do something different with this..",3); + console_message(collection[field]['simpl.ref'],3); + console_message("and I hope that was the number",3); + //null may be needed here... + target_object[field] = _simpl_ref_index_map[collection[field]['simpl.ref']]; + } + else + { + console_message("field of the collection or map",3); + console_message(field,3); + var item_key = target_object['_simpl_map_types_keys'][field]; + target_object[field] = castCollectionOrMap(target_object,collection,item_key); + } + } + } + //check on type of class descriptor + //target_object['_simpl_class_descriptor'] = simplDeserialize(target_object['_simpl_class_descriptor']); +} + + +/// +/// +/// +//graph part--------------- +//graphing happens with 2 passes of recursive functions +// +//1. pass, labels everything with a simpl_id +//2. pass, +// +// + +function getNewUnusedId() +{ + var same = 1; + var returnId = 1; + while(same) + { + returnId = ""+Math.floor(Math.random()*100000000); + if(!(returnId in _simpl_ref_index_map)) + same = 0; + } + return returnId; +} + +function isSimplObject(obj) +{ + if(!obj) + return false; + if(typeof(obj) == "object" && '_simpl_object_name' in obj) + return true; + return false; +} + +function cleanAsYouGo(obj, seen_before_things) +{ + if(!seen_before_things) + seen_before_things = {}; + + if(isSimplObject(obj)) + { + if(obj['simpl.id']) + { + if(obj['simpl.id'] in seen_before_things) + { + return obj; + } + seen_before_things[obj['simpl.id']] = 1; + } + } + for(var i in obj) { + //should only be for simpl objects inside of simpl objects but what about collections>>>??? + if(isSimplObject(obj[i])) + cleanAsYouGo(obj[i],seen_before_things); + } + + if(isSimplObject(obj)) + { + obj['simpl.id'] = null; + obj._seen_before = null; + } + return obj; +} + +function cleanupGraphContex(obj) +{ + console_message("cleanupGraphContex",3); + if(isSimplObject(obj)) + { + console_message("this is a simpl object",3); + if('_simpl_crumbs_cleanup' in obj) + { + console_message("simpl crumbs do exist",3); + for(var i=0; i>>??? + if(isSimplObject(obj[i])) + recursivlyGiveEachSimplObjectAnId(obj[i],crumb); + } + return obj; +} + +function recursivlyFillReferences(obj,old_clone) +{ + console_message("recursivlyFillReferences",3); + var clone = {}; + if(old_clone) + clone = old_clone; + for(var i in obj) + { + //if(typeof(obj[i]) == "object") + //{ + // clone[i] = obj[i]; + // console_message(i+" was just an object that should not be done anything with...",3); + + //} + //else + if(isSimplObject(obj[i]))//'_simpl_object_name' in obj[i]) + { + console_message("simpl object found",3); + if('simpl.id' in obj[i]) + { + console_message("simpl.id found in object",3); + if(obj[i]['simpl.id'] in _simpl_ref_index_map) + { + console_message("This object is already made, referencing it",3); + refedObj = {}; + refedNumber = {}; + refedNumber['simpl.ref'] = obj[i]['simpl.id']; + refedObj[obj['_simpl_object_name']] = refedNumber;//old bad + ////refedObj[i] = refedNumber; + clone[i] = refedNumber;//refedObj; + //refedNumber;//no really old + } + else + { + //add to _simpl_ref_index_map + //clone + console_message("This object has not been made. Making it.",3); + _simpl_ref_index_map[obj[i]['simpl.id']] = obj[i]; + clone[i] = obj[i]; + recursivlyFillReferences(obj[i],clone); + } + } + else + { + console_message("Cloneing field " + i + " with teh val "+obj[i],3); + clone[i] = obj[i]; + } + + } + else + { + console_message("Cloneing field " + i + " with teh val "+obj[i],3); + clone[i] = obj[i];//could probably make a better structure for this starement + } + } + return clone; } \ No newline at end of file diff --git a/simplTranslators/jscode/test.html b/simplTranslators/jscode/test.html index c991f02b..b66d8f95 100644 --- a/simplTranslators/jscode/test.html +++ b/simplTranslators/jscode/test.html @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/simplTranslators/lib/ST-4.0.5.jar b/simplTranslators/lib/ST-4.0.5.jar deleted file mode 100644 index 94ff2be6..00000000 Binary files a/simplTranslators/lib/ST-4.0.5.jar and /dev/null differ diff --git a/simplTranslators/lib/antlr-3.3-complete.jar b/simplTranslators/lib/antlr-3.3-complete.jar deleted file mode 100644 index d5a65aed..00000000 Binary files a/simplTranslators/lib/antlr-3.3-complete.jar and /dev/null differ diff --git a/simplTranslators/lib/junit.jar b/simplTranslators/lib/junit.jar deleted file mode 100644 index 7b232001..00000000 Binary files a/simplTranslators/lib/junit.jar and /dev/null differ diff --git a/simplTranslators/lib/pg73jdbc3.jar b/simplTranslators/lib/pg73jdbc3.jar deleted file mode 100644 index 04ee2d3c..00000000 Binary files a/simplTranslators/lib/pg73jdbc3.jar and /dev/null differ diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/DefaultDependencyTracker.java b/simplTranslators/newsrc/ecologylab/simpl/translators/DefaultDependencyTracker.java new file mode 100644 index 00000000..20b7bc46 --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/DefaultDependencyTracker.java @@ -0,0 +1,52 @@ +package ecologylab.simpl.translators; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Default implementation of DependencyTracker. + * + * @author quyin + * @author twhite + */ +public class DefaultDependencyTracker implements DependencyTracker +{ + + private Set trackedDependencies = new HashSet(); + + public void addDependency(String dependency) + { + if (dependency == null) + { + throw new NullPointerException("Dependency cannot be null!"); + } + this.trackedDependencies.add(dependency); + } + + public void addDependencies(Collection dependencies) + { + if (dependencies == null) + { + throw new NullPointerException("Dependencies cannot be null!"); + } + this.trackedDependencies.addAll(dependencies); + } + + public Set getDependencies() + { + return trackedDependencies; + } + + @Override + public List getOrderedDependencies() + { + List result = new ArrayList(trackedDependencies); + Collections.sort(result); + return result; + } + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/DependencyTracker.java b/simplTranslators/newsrc/ecologylab/simpl/translators/DependencyTracker.java new file mode 100644 index 00000000..73b49e35 --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/DependencyTracker.java @@ -0,0 +1,40 @@ +package ecologylab.simpl.translators; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +/** + * Tracking dependencies. + * + * @author quyin + * @author twhite + */ +public interface DependencyTracker +{ + + /** + * Add a single dependency. + * + * @param dependency + */ + void addDependency(String dependency); + + /** + * Add a collection of dependencies. + * + * @param dependencies + */ + void addDependencies(Collection dependencies); + + /** + * @return All dependencies tracked by this dependency tracker. + */ + Set getDependencies(); + + /** + * @return All dependencies tracked by this depedency tracker, ordered alphabetically. + */ + List getOrderedDependencies(); + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/EventDispatcher.java b/simplTranslators/newsrc/ecologylab/simpl/translators/EventDispatcher.java new file mode 100644 index 00000000..3fff164c --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/EventDispatcher.java @@ -0,0 +1,42 @@ +package ecologylab.simpl.translators; + +import java.util.Collection; + +/** + * An event dispatcher. + * + * @author quyin + * @param + */ +public interface EventDispatcher +{ + + /** + * Add a new eventHandler. + * + * @param eventHandler + */ + void addEventHandler(EventHandler eventHandler); + + /** + * Remove an existing eventHandler. + * + * @param eventHandler + */ + void removeEventHandler(EventHandler eventHandler); + + /** + * @return All existing eventHandlers. + */ + Collection getEventHandlers(); + + /** + * Dispatch an event (with given args) to all eventHandlers. + * + * The number and types of args should be consistent with the definition of EventHandler. + * + * @param args + */ + void dispatchEvent(Object... args); + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/TranslatorConfig.java b/simplTranslators/newsrc/ecologylab/simpl/translators/TranslatorConfig.java new file mode 100644 index 00000000..0364d4e9 --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/TranslatorConfig.java @@ -0,0 +1,82 @@ +package ecologylab.simpl.translators; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_scalar; + +/** + * Necessary configurations of a code translator. + * + * @author quyin + */ +public class TranslatorConfig +{ + + @simpl_scalar + private String typeLibraryClassNamespace; + + @simpl_scalar + private String typeLibraryClassSimpleName; + + @simpl_scalar + private File targetDir; + + @simpl_collection("excluded_class_name") + private List excludedClassNames; + + public String getTypeLibraryClassNamespace() + { + return typeLibraryClassNamespace; + } + + public void setTypeLibraryClassNamespace(String typeLibraryClassNamespace) + { + this.typeLibraryClassNamespace = typeLibraryClassNamespace; + } + + public String getTypeLibraryClassSimpleName() + { + return typeLibraryClassSimpleName; + } + + public void setTypeLibraryClassSimpleName(String typeLibraryClassSimpleName) + { + this.typeLibraryClassSimpleName = typeLibraryClassSimpleName; + } + + public File getTargetDir() + { + return targetDir; + } + + public void setTargetDir(File targetDir) + { + this.targetDir = targetDir; + } + + public List getExcludedClassNames() + { + return excludedClassNames; + } + + public void setExcludedClassNames(List excludedClassNames) + { + this.excludedClassNames = excludedClassNames; + } + + public void addExcludedClassName(String excludedClassName) + { + if (excludedClassNames == null) + { + excludedClassNames = new ArrayList(); + } + if (!excludedClassNames.contains(excludedClassName)) + { + excludedClassNames.add(excludedClassName); + } + } + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpClassTranslator.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpClassTranslator.java new file mode 100644 index 00000000..21ff612b --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpClassTranslator.java @@ -0,0 +1,355 @@ +package ecologylab.simpl.translators.csharp; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import ecologylab.generic.Debug; +import ecologylab.generic.HashMapArrayList; +import ecologylab.semantics.html.utils.StringBuilderUtils; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.MetaInformation; +import ecologylab.serialization.types.CollectionType; +import ecologylab.serialization.types.ScalarType; +import ecologylab.simpl.translators.DependencyTracker; +import ecologylab.translators.net.DotNetTranslationException; + +/** + * + * @author quyin + * + */ +public class CSharpClassTranslator extends Debug +{ + + private CSharpLanguageSpecifics langSpec; + + private CSharpNameTypeResolver nameTypeResolver; + + private CSharpFieldTranslator fieldTranslator; + + private CSharpMetaInformationTranslator metaInfoTranslator; + + private CSharpGenericTypeVariableTranslator gtvTranslator; + + private CSharpCommentTranslator commentTranslator; + + private DependencyTracker dependencyTracker; + + public CSharpClassTranslator(CSharpLanguageSpecifics langSpec, + CSharpNameTypeResolver nameTypeResolver, + CSharpFieldTranslator fieldTranslator, + CSharpMetaInformationTranslator metaInfoTranslator, + CSharpGenericTypeVariableTranslator gtvTranslator, + CSharpCommentTranslator commentTranslator) + { + super(); + this.langSpec = langSpec; + this.nameTypeResolver = nameTypeResolver; + this.fieldTranslator = fieldTranslator; + this.metaInfoTranslator = metaInfoTranslator; + this.gtvTranslator = gtvTranslator; + this.commentTranslator = commentTranslator; + } + + public DependencyTracker getDependencyTracker() + { + return dependencyTracker; + } + + void setDependencyTracker(DependencyTracker dependencyTracker) + { + this.dependencyTracker = dependencyTracker; + } + + /** + * The actual method converting a class descriptor into C# codes. + * + * @param inputClass + * @throws IOException + * @throws DotNetTranslationException + */ + public String translate(ClassDescriptor inputClass) throws IOException, + DotNetTranslationException + { + HashMapArrayList fieldDescriptors = + inputClass.getDeclaredFieldDescriptorsByFieldName(); + inputClass.resolvePolymorphicAnnotations(); + + String namespace = nameTypeResolver.resolveClassNamespace(inputClass); + String classSimpleName = nameTypeResolver.resolveClassSimpleName(inputClass); + + StringBuilder classDef = StringBuilderUtils.acquire(); + + // // file header + // StringBuilder header = StringBuilderUtils.acquire(); + // appendHeaderComments(inputClass.getDescribedClassSimpleName(), + // SINGLE_LINE_COMMENT, + // FILE_EXTENSION, + // header); + + // namespace + classDef.append("namespace ").append(namespace).append("\n"); + classDef.append("{\n"); + classDef.append("\n"); + + // class + // class: opening + classDef.append(translateClassComment(inputClass)); + appendClassMetaInformation(inputClass, classDef); + appendClassDeclaration(inputClass, classDef); + // class: fields + fieldTranslator.setDependencyTracker(dependencyTracker); + for (FieldDescriptor fieldDescriptor : fieldDescriptors) + { + if (fieldDescriptor.belongsTo(inputClass) + || inputClass.isCloned() && fieldDescriptor.belongsTo(inputClass.getClonedFrom())) + { + classDef.append("\n"); + fieldTranslator.translate(inputClass, fieldDescriptor, classDef); + // FIXME dependencies!!! + } + } + // class: constructor(s) + appendConstructor(inputClass, classDef, null); + // class: closing + classDef.append("\t"); + classDef.append("}"); + classDef.append("\n"); + + // unit scope: closing + classDef.append("}"); + classDef.append("\n"); + + // dependencies + // for (String dependency : deriveDependencies(inputClass)) + // { + // currentClassDependencies.add(javaPackage2CSharpNamespace(dependency)); + // } + // appendDependencies(currentClassDependencies, header); + // currentClassDependencies.clear(); + + // output + String rst = classDef.toString(); + StringBuilderUtils.release(classDef); + return rst; + } + + /** + * opens the c# class + * + * @param inputClass + * @param appendable + * @throws IOException + */ + protected void appendClassDeclaration(ClassDescriptor inputClass, Appendable appendable) + throws IOException + { + String classSimpleName = inputClass.getDescribedClassSimpleName(); + appendable.append(String.format(" public class %s", classSimpleName)); + appendClassGenericTypeVariables(appendable, inputClass); + + ClassDescriptor superCD = inputClass.getSuperClass(); + if (superCD != null) + { + appendable.append(" "); + appendable.append(":"); + appendable.append(" "); + appendable.append(superCD.getDescribedClassSimpleName()); + appendSuperClassGenericTypeVariables(appendable, inputClass); + String superClassDependency = + nameTypeResolver.javaPackage2CSharpNamespace(superCD.getCSharpNamespace()); + dependencyTracker.addDependency(superClassDependency); + } + + appendable.append("\n"); + appendable.append(" {\n"); + } + + /** + * Append class comments. + * + * @param inputClass + * @param appendable + * @throws IOException + */ + protected String translateClassComment(ClassDescriptor inputClass) + throws IOException + { + String comment = inputClass.getComment(); + if (comment != null && comment.length() > 0) + return commentTranslator.translateComment(" ", comment); + return ""; + } + + protected void appendClassMetaInformation(ClassDescriptor inputClass, Appendable appendable) + throws IOException + { + List metaInfo = inputClass.getMetaInformation(); + appendClassMetaInformationHook(inputClass, appendable); + metaInfoTranslator.setDependencyTracker(dependencyTracker); + if (metaInfo != null) + for (MetaInformation piece : metaInfo) + { + String metaInfoStr = metaInfoTranslator.translateMetaInformation(piece); + if (metaInfoStr != null && metaInfoStr.length() > 0) + appendable.append(" ").append(metaInfoStr); + } + } + + protected void appendClassMetaInformationHook(ClassDescriptor inputClass, Appendable appendable) + { + // empty implementation + } + + /** + * @param appendable + * @param inputClass + * @throws IOException + */ + protected void appendClassGenericTypeVariables(Appendable appendable, ClassDescriptor inputClass) + throws IOException + { + appendable.append(gtvTranslator.toDefinitionWithGenerics(inputClass)); + } + + protected void appendSuperClassGenericTypeVariables(Appendable appendable, + ClassDescriptor inputClass) + throws IOException + { + // StringBuilder sb = new StringBuilder(); + // List genericTypeVars = inputClass.getGenericTypeVars(); + // if (genericTypeVars != null && genericTypeVars.size() > 0) + // { + // sb.append(" where "); + // int len = sb.length(); + // for (int i = 0; i < genericTypeVars.size(); ++i) + // { + // GenericTypeVar genericTypeVar = genericTypeVars.get(i); + // sb.append(i == 0 ? "" : ", "); + // if (genericTypeVar.getConstraintGenericTypeVar() != null) + // { + // sb.append(genericTypeVar.getName()).append(" : ") + // .append(genericTypeVar.getConstraintGenericTypeVar().getName()); + // } + // else if (genericTypeVar.getConstraintClassDescriptor() != null) + // { + // sb.append(genericTypeVar.getName()).append(" : ") + // .append(genericTypeVar.getConstraintClassDescriptor().getDescribedClassSimpleName()); + // List CGTVargs = genericTypeVar.getConstraintGenericTypeVarArgs(); + // if (CGTVargs != null && CGTVargs.size() > 0) + // { + // sb.append('<'); + // for (int j = 0; j < CGTVargs.size(); ++j) + // { + // GenericTypeVar cgtv = CGTVargs.get(j); + // sb.append(j == 0 ? "" : ", ").append(cgtv.getName()); + // } + // sb.append('>'); + // } + // } + // else + // { + // warning("Unprocessed generic type var: " + genericTypeVar); + // } + // } + // if (sb.length() > len) + // appendable.append(sb); + // } + } + + private Set deriveDependencies(ClassDescriptor inputClass) + { + Set dependencies = new HashSet(); + + Set scalars = inputClass.deriveScalarDependencies(); + for (ScalarType scalar : scalars) + dependencies.add(scalar.getCSharpNamespace()); + + Set composites = inputClass.deriveCompositeDependencies(); + for (ClassDescriptor composite : composites) + dependencies.add(composite.getCSharpNamespace()); + + Set collections = inputClass.deriveCollectionDependencies(); + for (CollectionType collection : collections) + dependencies.add(collection.getCSharpNamespace()); + + return dependencies; + } + + /** + * @param inputClass + * @param appendable + * @throws IOException + */ + protected void appendConstructor(ClassDescriptor inputClass, + Appendable appendable, + String className) + throws IOException + { + appendDefaultConstructor(inputClass.getDescribedClassSimpleName(), appendable); + + appendConstructorHook(inputClass, appendable, null); + } + + protected void appendConstructorHook(ClassDescriptor inputClass, + Appendable appendable, + String classSimpleName) throws IOException + { + // for derived classes to use. + } + + /** + * @param className + * @param appendable + * @throws IOException + */ + protected void appendDefaultConstructor(String className, Appendable appendable) + throws IOException + { + appendable.append("\n"); + appendable.append(String.format(" public %s()\n", className)); + appendable.append(" { }\n"); + } + + /** + * Append class header comment. + * + * @param className + * The target class name. + * @param singleLineComment + * The single line comment leading pattern. + * @param fileExtension + * The extension of generated source code file (with dot). + * @param appendable + * The appendable target. + * @throws IOException + */ + protected void appendHeaderComments(String className, + String singleLineComment, + String fileExtension, + Appendable appendable) throws IOException + { + DateFormat dateFormat = new SimpleDateFormat("MM/dd/yy"); + DateFormat yearFormat = new SimpleDateFormat("yyyy"); + + Date date = new Date(); + + appendable.append(singleLineComment + "\n" + + singleLineComment + " " + className + fileExtension + "\n" + + singleLineComment + " s.im.pl serialization\n" + + singleLineComment + "\n" + + singleLineComment + " Generated by " + this.getClass().getSimpleName() + + ".\n" + + singleLineComment + " Copyright " + yearFormat.format(date) + + " Interface Ecology Lab. \n" + + singleLineComment + "\n\n" + ); + } + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpCommentTranslator.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpCommentTranslator.java new file mode 100644 index 00000000..c99ac35a --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpCommentTranslator.java @@ -0,0 +1,31 @@ +package ecologylab.simpl.translators.csharp; + +/** + * + * @author quyin + * + */ +public class CSharpCommentTranslator +{ + + /** + * + * @param spacing + * @param comments + * @return + */ + public String translateComment(String spacing, String... comments) + { + StringBuilder sb = new StringBuilder(); + sb.append(spacing); + sb.append("/// \n"); + if (comments != null && comments.length > 0) + for (String comment : comments) + sb.append(spacing).append("/// ").append(comment).append("\n"); + else + sb.append(spacing).append("/// (missing comments)\n"); + sb.append(spacing).append("/// \n"); + return sb.toString(); + } + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpDependencyComparator.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpDependencyComparator.java new file mode 100644 index 00000000..f3406b4e --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpDependencyComparator.java @@ -0,0 +1,71 @@ +package ecologylab.simpl.translators.csharp; + +import java.util.Comparator; + +/** + * + * @author quyin + * + */ +public class CSharpDependencyComparator implements Comparator +{ + + private static String[] BUILTIN_NAMESPACE_PREFIXES; + + static + { + BUILTIN_NAMESPACE_PREFIXES = new String[] + { + "System", + "System.", + "Ecologylab", + "Ecologylab.", + "Simpl", + "Simpl.", + }; + } + + /** + * + */ + @Override + public int compare(String dep1, String dep2) + { + if (dep1 == null || dep2 == null) + throw new NullPointerException("Non-null argument expected."); + + int p1 = getBuiltinNamespacePrefixIndex(dep1); + int p2 = getBuiltinNamespacePrefixIndex(dep2); + + if (p1 == p2) + return dep1.compareTo(dep2); + else + return p1 - p2; + } + + /** + * + * @return + */ + protected String[] getBuiltinNamespacePrefixes() + { + return BUILTIN_NAMESPACE_PREFIXES; + } + + /** + * + * @param dep + * @return + */ + protected int getBuiltinNamespacePrefixIndex(String dep) + { + if (dep == null) + throw new NullPointerException("Non-null argument expected."); + + String[] builtinNamespacePrefixes = getBuiltinNamespacePrefixes(); + for (int i = 0; i < builtinNamespacePrefixes.length; ++i) + if (dep.startsWith(builtinNamespacePrefixes[i])) + return i; + return Integer.MAX_VALUE; + } +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpDependencyTranslator.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpDependencyTranslator.java new file mode 100644 index 00000000..05d3c895 --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpDependencyTranslator.java @@ -0,0 +1,76 @@ +package ecologylab.simpl.translators.csharp; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import ecologylab.simpl.translators.DependencyTranslator; + +/** + * + * @author quyin + * + */ +public class CSharpDependencyTranslator implements DependencyTranslator +{ + + private static Comparator depComparator = new CSharpDependencyComparator(); + + private static Set globalDependencies = new HashSet(); + + static + { + globalDependencies.add("System"); + globalDependencies.add("System.Collections"); + globalDependencies.add("System.Collections.Generic"); + globalDependencies.add("Simpl.Serialization"); + globalDependencies.add("Simpl.Serialization.Attributes"); + globalDependencies.add("Simpl.Fundamental.Generic"); + globalDependencies.add("Ecologylab.Collections"); + } + + @Override + public Set getGlobalDependencies() + { + return globalDependencies; + } + + /** + * + * @return + */ + protected Comparator getDependencyComparator() + { + return depComparator; + } + + @Override + public String translateDependency(String dependency) + { + return dependency == null ? "" : "using " + dependency + ";\n"; + } + + @Override + public String translateDependencies(Set dependencies) + { + List sortedDeps = new ArrayList(); + + Set allDeps = new HashSet(); + allDeps.addAll(getGlobalDependencies()); + if (dependencies != null) + allDeps.addAll(dependencies); + + for (String dep : allDeps) + sortedDeps.add(dep); + Collections.sort(sortedDeps, getDependencyComparator()); + + StringBuilder sb = new StringBuilder(); + for (String dep : sortedDeps) + sb.append(translateDependency(dep)); + return sb.toString(); + } + +} \ No newline at end of file diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpFieldTranslator.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpFieldTranslator.java new file mode 100644 index 00000000..949e6801 --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpFieldTranslator.java @@ -0,0 +1,169 @@ +package ecologylab.simpl.translators.csharp; + +import java.io.IOException; +import java.util.List; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.MetaInformation; +import ecologylab.simpl.translators.DependencyTracker; +import ecologylab.translators.net.DotNetTranslationException; +import ecologylab.translators.net.DotNetTranslationUtilities; + +public class CSharpFieldTranslator +{ + + private CSharpNameTypeResolver nameTypeResolver; + + private CSharpLanguageSpecifics langSpec; + + private CSharpCommentTranslator commentTranslator; + + private CSharpMetaInformationTranslator metaInfoTranslator; + + private CSharpGenericTypeVariableTranslator gtvTranslator; + + private DependencyTracker dependencyTracker; + + public CSharpFieldTranslator(CSharpNameTypeResolver nameTypeResolver, + CSharpLanguageSpecifics langSpec, + CSharpCommentTranslator commentTranslator, + CSharpMetaInformationTranslator metaInfoTranslator, + CSharpGenericTypeVariableTranslator gtvTranslator) + { + super(); + this.nameTypeResolver = nameTypeResolver; + this.langSpec = langSpec; + this.commentTranslator = commentTranslator; + this.metaInfoTranslator = metaInfoTranslator; + this.gtvTranslator = gtvTranslator; + } + + /** + * Append a field to the translated class source. + * + * @param context + * @param fieldDescriptor + * @param appendable + * @throws IOException + * @throws DotNetTranslationException + */ + public void translate(ClassDescriptor context, + FieldDescriptor fieldDescriptor, + Appendable appendable) + throws IOException, DotNetTranslationException + { + String cSharpType = nameTypeResolver.resolveFieldType(fieldDescriptor); + if (cSharpType == null) + { + System.out.println("ERROR, no valid CSharpType found for : " + fieldDescriptor); + return; + } + + boolean isKeyword = langSpec.checkForKeywords(fieldDescriptor); + if (isKeyword) + appendable.append("/*\n"); + appendFieldComments(fieldDescriptor, appendable); + appendFieldMetaInformation(context, fieldDescriptor, appendable); + appendable.append(String.format(" private %s %s;\n", cSharpType, fieldDescriptor.getName())); + if (isKeyword) + appendable.append("*/\n"); + + appendGettersAndSetters(context, fieldDescriptor, cSharpType, appendable); + } + + protected void appendFieldGenericTypeVars(ClassDescriptor contextCd, + FieldDescriptor fieldDescriptor, + Appendable appendable) + throws IOException + { + // TODO Auto-generated method stub + + } + + /** + * @param fieldDescriptor + * @param appendable + * @throws IOException + */ + protected void appendFieldComments(FieldDescriptor fieldDescriptor, Appendable appendable) + throws IOException + { + String comment = fieldDescriptor.getComment(); + if (comment != null && comment.length() > 0) + appendable.append(commentTranslator.translateComment(" ", comment)); + } + + protected void appendFieldMetaInformation(ClassDescriptor contextCd, + FieldDescriptor fieldDescriptor, + Appendable appendable) throws IOException + { + List metaInfo = fieldDescriptor.getMetaInformation(); + appendFieldMetaInformationHook(contextCd, fieldDescriptor, appendable); + if (metaInfo != null) + for (MetaInformation piece : metaInfo) + { + String metaInfoStr = metaInfoTranslator.translateMetaInformation(piece); + if (metaInfoStr != null && metaInfoStr.length() > 0) + appendable.append(" ").append(metaInfoStr); + } + } + + protected void appendFieldMetaInformationHook(ClassDescriptor contextCd, + FieldDescriptor fieldDesc, + Appendable appendable) throws IOException + { + // for derived classes to use. + } + + /** + * @param context + * @param fieldDescriptor + * @param appendable + * @throws IOException + */ + protected void appendGettersAndSetters(ClassDescriptor context, + FieldDescriptor fieldDescriptor, + String type, + Appendable appendable) + throws IOException + { + String cSharpType = type; + + appendable.append("\n"); + + String fieldName = fieldDescriptor.getName(); + String propertyName = DotNetTranslationUtilities.getPropertyName(context, fieldDescriptor); + boolean isKeyword = langSpec.checkForKeywords(fieldDescriptor); + if (isKeyword) + appendable.append("/*\n"); + appendable.append(String.format(" public %s %s\n", cSharpType, propertyName)); + appendable.append(String.format(" {\n")); + appendable.append(String.format(" get { return %s; }\n", fieldName)); + appendable.append(String.format(" set\n")); + appendable.append(String.format(" {\n")); + appendable.append(String.format(" if (this.%s != value)\n", fieldName)); + appendable.append(String.format(" {\n")); + appendable.append(String.format(" this.%s = value;\n", fieldName)); + appendable.append(String.format(" }\n")); + appendable.append(String.format(" }\n")); + appendable.append(String.format(" }\n")); + if (isKeyword) + appendable.append("*/\n"); + + appendGettersAndSettersHook(context, fieldDescriptor, appendable); + } + + protected void appendGettersAndSettersHook(ClassDescriptor context, + FieldDescriptor fieldDescriptor, Appendable appendable) + { + // TODO Auto-generated method stub + + } + + void setDependencyTracker(DependencyTracker dependencyTracker) + { + this.dependencyTracker = dependencyTracker; + } + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpGenericTypeVariableTranslator.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpGenericTypeVariableTranslator.java new file mode 100644 index 00000000..3d843c37 --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpGenericTypeVariableTranslator.java @@ -0,0 +1,118 @@ +package ecologylab.simpl.translators.csharp; + +import java.util.List; + +import ecologylab.generic.Debug; +import ecologylab.semantics.html.utils.StringBuilderUtils; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.GenericTypeVar; +import ecologylab.simpl.translators.DependencyTracker; +import ecologylab.translators.net.DotNetGenericsUtils; + +public class CSharpGenericTypeVariableTranslator +{ + + private DependencyTracker dependencyTracker; + + public String toDefinitionWithGenerics(ClassDescriptor classDescriptor) + { + StringBuilder sb = StringBuilderUtils.acquire(); + + // class name, and generic type var list if any +// sb.append(classDescriptor.getDescribedClassSimpleName()); + List gtvs = classDescriptor.getGenericTypeVars(); + if (gtvs != null && gtvs.size() > 0) + { + sb.append('<'); + for (int i = 0; i < gtvs.size(); ++i) + { + GenericTypeVar gtv = gtvs.get(i); + sb.append(i == 0 ? "" : ", ").append(gtv.getName()); + } + sb.append('>'); + } + + // super class + ClassDescriptor superClassDescriptor = classDescriptor.getSuperClass(); + if (superClassDescriptor != null) + { + sb.append(" : ").append(toDeclarationWithGenerics( + superClassDescriptor, + classDescriptor.getSuperClassGenericTypeVars())); + } + + // where clauses: + if (gtvs != null && gtvs.size() > 0) + { + for (int i = 0; i < gtvs.size(); ++i) + { + GenericTypeVar gtv = gtvs.get(i); + if (gtv.getConstraintGenericTypeVar() != null) + { + sb.append(" where "); + String constraintGTVname = gtv.getConstraintGenericTypeVar().getName(); + if ("?".equals(constraintGTVname)) + { + constraintGTVname = gtv.getConstraintGenericTypeVar() + .getConstraintGenericTypeVar().getName(); + } + sb.append(gtv.getName()).append(" : ") + .append(constraintGTVname); + } + else if (gtv.getConstraintClassDescriptor() != null) + { + sb.append(" where "); + sb.append(gtv.getName()).append(" : ") + .append(toDeclarationWithGenerics(gtv.getConstraintClassDescriptor(), + gtv.getConstraintGenericTypeVarArgs())); + } + else + { + Debug.warning(DotNetGenericsUtils.class, "Unprocessed generic type var: " + gtv); + } + } + } + + String result = sb.toString(); + StringBuilderUtils.release(sb); + return result; + } + + public String toDeclarationWithGenerics(ClassDescriptor classDescriptor) + { + return toDeclarationWithGenerics(classDescriptor, classDescriptor.getGenericTypeVars()); + } + + protected String toDeclarationWithGenerics(ClassDescriptor classDescriptor, + List genericTypeVars) + { + StringBuilder sb = StringBuilderUtils.acquire(); + sb.append(classDescriptor.getDescribedClassSimpleName()); + if (genericTypeVars != null && genericTypeVars.size() > 0) + { + sb.append('<'); + for (int i = 0; i < genericTypeVars.size(); ++i) + { + GenericTypeVar gtv = genericTypeVars.get(i); + sb.append(i == 0 ? "" : ", "); + + if (gtv.getClassDescriptor() != null) + { + sb.append(gtv.getClassDescriptor().getDescribedClassSimpleName()); + } + else if (gtv.getName() != null) + { + String gtvName = gtv.getName(); + if ("?".equals(gtvName)) + gtvName = gtv.getConstraintGenericTypeVar().getName(); + sb.append(gtvName); + } + } + sb.append('>'); + } + String result = sb.toString(); + StringBuilderUtils.release(sb); + return result; + } + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpLanguageSpecifics.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpLanguageSpecifics.java new file mode 100644 index 00000000..5c2564c4 --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpLanguageSpecifics.java @@ -0,0 +1,25 @@ +package ecologylab.simpl.translators.csharp; + +import ecologylab.generic.Debug; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.translators.net.DotNetTranslationUtilities; + +public class CSharpLanguageSpecifics +{ + + /** + * @param fieldDescriptor + * @return true if the name is a keyword, otherwise false. + */ + public boolean checkForKeywords(FieldDescriptor fieldDescriptor) + { + if (DotNetTranslationUtilities.isKeyword(fieldDescriptor.getName())) + { + Debug.warning(fieldDescriptor, "Field [" + fieldDescriptor.getName() + + "]: This is a keyword in C#. Cannot translate."); + return true; + } + return false; + } + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpMetaInformationTranslator.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpMetaInformationTranslator.java new file mode 100644 index 00000000..684c4f1d --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpMetaInformationTranslator.java @@ -0,0 +1,118 @@ +package ecologylab.simpl.translators.csharp; + +import java.io.IOException; + +import ecologylab.semantics.html.utils.StringBuilderUtils; +import ecologylab.serialization.MetaInformation; +import ecologylab.serialization.MetaInformation.Argument; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.simpl.translators.DependencyTracker; +import ecologylab.translators.net.DotNetTranslationUtilities; + +public class CSharpMetaInformationTranslator +{ + + private DependencyTracker dependencyTracker; + + public String translateMetaInformation(MetaInformation metaInfo) throws IOException + { + if (isAttributeHint(metaInfo)) + return ""; + + String metaInfoPackage = metaInfo.typeName.substring(0, metaInfo.typeName.lastIndexOf('.')); + String metaInfoDependency = DotNetTranslationUtilities + .translateAnnotationPackage(metaInfoPackage); + if (metaInfoDependency != null) + dependencyTracker.addDependency(metaInfoDependency); + + StringBuilder sb = StringBuilderUtils.acquire(); + + sb.append("["); + sb.append(DotNetTranslationUtilities.translateAnnotationName(metaInfo.simpleTypeName)); + if (metaInfo.args != null && metaInfo.args.size() > 0) + { + sb.append("("); + if (metaInfo.argsInArray) + { + String argType = metaInfo.args.get(0).simpleTypeName; + if (argType.equals("Class")) + argType = "Type"; + sb.append("new ").append(argType).append("[] {"); + for (int i = 0; i < metaInfo.args.size(); ++i) + sb.append(i == 0 ? "" : ", ") + .append(translateMetaInfoArgValue(metaInfo.args.get(i).value)); + sb.append("}"); + } + else + { + for (int i = 0; i < metaInfo.args.size(); ++i) + { + Argument a = metaInfo.args.get(i); + sb.append(i == 0 ? "" : ", ") + .append(metaInfo.args.size() > 1 ? a.name + " = " : "") + .append(translateMetaInfoArgValue(a.value)); + } + } + sb.append(")"); + } + sb.append("]"); + sb.append("\n"); + + String metaInfoStr = sb.toString(); + StringBuilderUtils.release(sb); + return metaInfoStr; + } + + private boolean isAttributeHint(MetaInformation metaInfo) + { + if (simpl_hints.class.getName().equals(metaInfo.typeName) + && metaInfo.argsInArray + && metaInfo.args != null + && metaInfo.args.size() == 1 + && metaInfo.args.get(0).value != null + && metaInfo.args.get(0).value.equals(Hint.XML_ATTRIBUTE)) + return true; + return false; + } + + protected String translateMetaInfoArgValue(Object argValue) + { + // TODO to make this extendible, use an interface MetaInfoArgValueTranslator and allow users + // to inject new ones to handle different kind of cases. + if (argValue instanceof String) + { + return "\"" + argValue.toString() + "\""; + } + else if (argValue instanceof Hint) + { + switch ((Hint) argValue) + { + case XML_ATTRIBUTE: + return "Hint.XmlAttribute"; + case XML_LEAF: + return "Hint.XmlLeaf"; + case XML_LEAF_CDATA: + return "Hint.XmlLeafCdata"; + case XML_TEXT: + return "Hint.XmlText"; + case XML_TEXT_CDATA: + return "Hint.XmlTextCdata"; + default: + return "Hint.Undefined"; + } + } + else if (argValue instanceof Class) + { + return "typeof(" + ((Class) argValue).getSimpleName() + ")"; + } + // eles if (argValue instanceof ClassDescriptor) + return null; + } + + void setDependencyTracker(DependencyTracker dependencyTracker) + { + this.dependencyTracker = dependencyTracker; + } + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpNameTypeResolver.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpNameTypeResolver.java new file mode 100644 index 00000000..71652636 --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpNameTypeResolver.java @@ -0,0 +1,68 @@ +package ecologylab.simpl.translators.csharp; + +import ecologylab.semantics.html.utils.StringBuilderUtils; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; + +public class CSharpNameTypeResolver +{ + + public String resolveClassNamespace(ClassDescriptor classDescriptor) + { + // TODO built-in namespaces conversion + String javaPackage = classDescriptor.getDescribedClassPackageName(); + return javaPackage2CSharpNamespace(javaPackage); + } + + public String resolveClassSimpleName(ClassDescriptor classDescriptor) + { + // TODO built-in type name conversion + return classDescriptor.getDescribedClassSimpleName(); + } + + public String resolveFieldType(FieldDescriptor fieldDescriptor) + { + // TODO built-in type conversion + String cSharpType = fieldDescriptor.getCSharpType(); + return cSharpType == null ? null : javaType2CSharpTypeWithNamespaceFix(cSharpType); + } + + private String javaType2CSharpTypeWithNamespaceFix(String cSharpType) + { + if (cSharpType.contains(".")) + { + // adapt java style package into C# namespace + + int p0 = cSharpType.indexOf('<'); + int p1 = cSharpType.indexOf('>'); + String prefix = p0 >= 0 ? cSharpType.substring(0, p0 + 1) : ""; + String suffix = p1 >= 0 ? cSharpType.substring(p1) : ""; + String typeStr = p0 >= 0 && p1 >= 0 ? cSharpType.substring(p0 + 1, p1) : cSharpType; + + int p = typeStr.lastIndexOf('.'); + String packageName = typeStr.substring(0, p); + String className = typeStr.substring(p + 1); + + typeStr = javaPackage2CSharpNamespace(packageName) + "." + className; + + cSharpType = prefix + typeStr + suffix; + } + return cSharpType; + } + + public String javaPackage2CSharpNamespace(String packageName) + { + StringBuilder sb = StringBuilderUtils.acquire(); + for (int i = 0; i < packageName.length(); ++i) + { + char c = packageName.charAt(i); + char pc = i == 0 ? 0 : packageName.charAt(i - 1); + if (c != '_') + sb.append((i == 0 || pc == '.' || pc == '_') ? Character.toUpperCase(c) : c); + } + String result = sb.toString(); + StringBuilderUtils.release(sb); + return result; + } + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpScopeTranslator.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpScopeTranslator.java new file mode 100644 index 00000000..7975cf17 --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpScopeTranslator.java @@ -0,0 +1,173 @@ +package ecologylab.simpl.translators.csharp; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import ecologylab.generic.Debug; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.simpl.translators.DependencyTracker; +import ecologylab.simpl.translators.DefaultDependencyTracker; +import ecologylab.simpl.translators.EventDispatcher; +import ecologylab.translators.CodeTranslatorConfig; +import ecologylab.translators.net.DotNetTranslationException; + +/** + * + * @author quyin + * + */ +public class CSharpScopeTranslator extends Debug implements + EventDispatcher +{ + + private Set excludedClassNames = new HashSet(); + + private CSharpNameTypeResolver nameTypeResolver; + + private CSharpCommentTranslator commentTranslator; + + private CSharpMetaInformationTranslator metaInfoTranslator; + + private CSharpGenericTypeVariableTranslator gtvTranslator; + + private CSharpLanguageSpecifics langSpec; + + private CSharpFieldTranslator fieldTranslator; + + private CSharpClassTranslator classTranslator; + + private List classTranslatedEventHandlers; + + public CSharpScopeTranslator() + { + super(); + + nameTypeResolver = new CSharpNameTypeResolver(); + commentTranslator = new CSharpCommentTranslator(); + metaInfoTranslator = new CSharpMetaInformationTranslator(); + gtvTranslator = new CSharpGenericTypeVariableTranslator(); + langSpec = new CSharpLanguageSpecifics(); + + fieldTranslator = new CSharpFieldTranslator(nameTypeResolver, + langSpec, + commentTranslator, + metaInfoTranslator, + gtvTranslator); + + classTranslator = new CSharpClassTranslator(langSpec, + nameTypeResolver, + fieldTranslator, + metaInfoTranslator, + gtvTranslator, + commentTranslator); + } + + /** + * + * @param typeScope + * @param config + * @return + * @throws IOException + * @throws SIMPLTranslationException + * @throws DotNetTranslationException + */ + public void translate(SimplTypesScope typeScope, CodeTranslatorConfig config) + throws IOException, SIMPLTranslationException, DotNetTranslationException + { + debug("Generating C# classes ..."); + + Collection> classes = + typeScope.entriesByClassName().values(); + for (ClassDescriptor classDescriptor : classes) + { + String name = classDescriptor.getName(); + if (excludedClassNames.contains(name)) + { + debug("Excluding " + classDescriptor + "from translation as requested."); + continue; + } + DependencyTracker dependencyTracker = new DefaultDependencyTracker(); + classTranslator.setDependencyTracker(dependencyTracker); + String classDef = classTranslator.translate(classDescriptor); + if (classDef != null && classDef.length() > 0) + { + String classNamespace = nameTypeResolver.resolveClassNamespace(classDescriptor); + String classSimpleName = nameTypeResolver.resolveClassSimpleName(classDescriptor); + dispatchEvent(classNamespace, + classSimpleName, + classDef, + dependencyTracker.getDependencies()); + } + } + + debug("DONE !"); + } + + /** + * @param classDescriptor + */ + public void excludeClassFromTranslation(ClassDescriptor classDescriptor) + { + if (classDescriptor != null) + excludeClassFromTranslation(classDescriptor.getName()); + } + + /** + * @param className + */ + public void excludeClassFromTranslation(String className) + { + if (className != null && className.length() > 0) + excludedClassNames.add(className); + } + + @Override + public void addEventHandler(ClassTranslatedEventHandler eventHandler) + { + if (classTranslatedEventHandlers == null) + classTranslatedEventHandlers = new ArrayList(); + classTranslatedEventHandlers.add(eventHandler); + } + + @Override + public void removeEventHandler(ClassTranslatedEventHandler eventHandler) + { + if (classTranslatedEventHandlers != null) + classTranslatedEventHandlers.remove(eventHandler); + } + + @Override + public Collection getEventHandlers() + { + return classTranslatedEventHandlers; + } + + @Override + public void dispatchEvent(Object... args) + { + if (classTranslatedEventHandlers != null) + if (args != null && args.length == 4) + { + String classNamespace = (String) args[0]; + String classSimpleName = (String) args[1]; + String classDef = (String) args[2]; + Set dependencies = null; + if (args[3] instanceof Set) + dependencies = (Set) args[3]; + + for (ClassTranslatedEventHandler eventHandler : classTranslatedEventHandlers) + eventHandler.classTranslated(classNamespace, + classSimpleName, + classDef, + dependencies); + } + } + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpTranslator.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpTranslator.java new file mode 100644 index 00000000..3d707436 --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpTranslator.java @@ -0,0 +1,162 @@ +package ecologylab.simpl.translators.csharp; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Set; + +import ecologylab.appframework.PropertiesAndDirectories; +import ecologylab.generic.Debug; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.simpl.translators.DefaultDependencyTracker; +import ecologylab.translators.CodeTranslatorConfig; +import ecologylab.translators.net.DotNetTranslationException; + +/** + * + * @author quyin + * + */ +public class CSharpTranslator extends Debug +{ + + private CSharpScopeTranslator scopeTranslator; + + private CSharpNameTypeResolver nameTypeResolver; + + private CSharpTypeLibraryTranslator typeLibTranslator; + + private CSharpDependencyTranslator dependencyTranslator; + + /** + * + */ + public CSharpTranslator() + { + scopeTranslator = new CSharpScopeTranslator(); + nameTypeResolver = new CSharpNameTypeResolver(); + typeLibTranslator = new CSharpTypeLibraryTranslator(); + dependencyTranslator = new CSharpDependencyTranslator(); + + typeLibTranslator.excludedClassNames = scopeTranslator.excludedClassNames; + typeLibTranslator.nameTypeResolver = nameTypeResolver; + } + + /** + * + * @param typeScope + * @param parentDir + * @param config + * @throws IOException + * @throws DotNetTranslationException + * @throws SIMPLTranslationException + */ + public void translate(SimplTypesScope typeScope, + final File parentDir, + CodeTranslatorConfig config) + throws IOException, DotNetTranslationException, SIMPLTranslationException + { + ClassTranslatedEventHandler eventHandler = new ClassTranslatedEventHandler() + { + @Override + public void classTranslated(String classNamespace, + String classSimpleName, + String classDef, + Set dependencies) + { + writeTranslatedClass(parentDir, classNamespace, classSimpleName, classDef, dependencies); + } + }; + scopeTranslator.addEventHandler(eventHandler); + scopeTranslator.translate(typeScope, config); + scopeTranslator.removeEventHandler(eventHandler); + + String typeLibClassDef = + typeLibTranslator.generateTypeLibraryClass(typeScope, + typeScope.getName(), + config.getLibraryTScopeClassPackage(), + config.getLibraryTScopeClassSimpleName(), + parentDir); + writeTranslatedClass(parentDir, + config.getLibraryTScopeClassPackage(), + config.getLibraryTScopeClassSimpleName(), + typeLibClassDef, + null); + } + + /** + * + * @param parentDir + * @param classNamespace + * @param classSimpleName + * @param classDef + * @param dependencies + */ + protected void writeTranslatedClass(final File parentDir, + String classNamespace, + String classSimpleName, + String classDef, + Set dependencies) + { + File outputFile = null; + try + { + outputFile = createFileWithDirStructure(parentDir, + classNamespace.split("\\."), + classSimpleName, + ".cs"); + } + catch (IOException e) + { + error("Cannot create file for " + classNamespace + "." + classSimpleName); + e.printStackTrace(); + } + + BufferedWriter bufferedWriter; + try + { + bufferedWriter = new BufferedWriter(new FileWriter(outputFile)); + bufferedWriter.append(dependencyTranslator.translateDependencies(dependencies)); + bufferedWriter.append(classDef); + bufferedWriter.close(); + } + catch (IOException e) + { + error("Cannot write to file " + outputFile); + e.printStackTrace(); + } + } + + /** + * + * @param parentDir + * @param dirStructure + * @param name + * @param extension + * @return + * @throws IOException + */ + protected File createFileWithDirStructure(File parentDir, + String[] dirStructure, + String name, + String extension) + throws IOException + { + File dir = parentDir; + for (String directoryName : dirStructure) + { + dir = new File(dir, directoryName); + } + PropertiesAndDirectories.createDirsAsNeeded(dir); + + File file = new File(dir, name + extension); + if (file.exists()) + file.delete(); + file.createNewFile(); + + return file; + } + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpTypeLibraryTranslator.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpTypeLibraryTranslator.java new file mode 100644 index 00000000..58ee330b --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/CSharpTypeLibraryTranslator.java @@ -0,0 +1,155 @@ +package ecologylab.simpl.translators.csharp; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import ecologylab.semantics.html.utils.StringBuilderUtils; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.simpl.translators.DependencyTracker; +import ecologylab.translators.net.DotNetTranslationConstants; + +public class CSharpTypeLibraryTranslator implements DotNetTranslationConstants +{ + + Set excludedClassNames; + + DependencyTracker dependencyTracker; + + CSharpNameTypeResolver nameTypeResolver; + + /** + * + * @param typeScope + * @param libraryTypeScopeName + * @param libraryNamespace + * @param libraryClassName + * @param parentDir + * @throws IOException + */ + public String generateTypeLibraryClass(SimplTypesScope typeScope, + String libraryTypeScopeName, + String libraryNamespace, + String libraryClassName, + File parentDir) throws IOException + { + StringBuilder sb = StringBuilderUtils.acquire(); + + // append notice information + sb.append("\n"); + sb.append("// Developer should proof-read this TranslationScope before using it " + + "for production.\n"); + sb.append("\n"); + + // header + sb.append(NAMESPACE); + sb.append(SPACE); + sb.append(libraryNamespace); + sb.append(SPACE); + sb.append(SINGLE_LINE_BREAK); + sb.append(OPENING_CURLY_BRACE); + sb.append(SINGLE_LINE_BREAK); + + // class: header + sb.append(" "); + sb.append(PUBLIC); + sb.append(SPACE); + sb.append(CLASS); + sb.append(SPACE); + sb.append(libraryClassName); + sb.append(SINGLE_LINE_BREAK); + sb.append(" "); + sb.append(OPENING_CURLY_BRACE); + sb.append(SINGLE_LINE_BREAK); + + // class: constructor + appendDefaultConstructor(libraryClassName, sb); + + // class: the Get() method + generateLibraryTScopeGetter(sb, typeScope, libraryTypeScopeName); + + sb.append("\n }\n"); + sb.append("\n}\n"); + + String result = sb.toString(); + StringBuilderUtils.release(sb); + return result; + } + + protected void generateLibraryTScopeGetter(Appendable appendable, + SimplTypesScope tScope, + String typeScopeName) + throws IOException + { + appendable.append(SINGLE_LINE_BREAK); + appendable.append(" "); + appendable.append(PUBLIC); + appendable.append(SPACE); + appendable.append(STATIC); + appendable.append(SPACE); + appendable.append(DOTNET_TRANSLATION_SCOPE); + appendable.append(SPACE); + appendable.append("Get()\n"); + appendable.append(" "); + appendable.append(OPENING_CURLY_BRACE); + appendable.append(SINGLE_LINE_BREAK); + + appendable.append(" "); + appendable.append(RETURN); + appendable.append(SPACE); + appendable.append(DOTNET_TRANSLATION_SCOPE); + appendable.append(DOT); + appendable.append(FGET); + appendable.append(OPENING_BRACE); + appendable.append("\n "); + appendable.append(QUOTE); + appendable.append(tScope.getName()); + appendable.append(QUOTE); + appendTranslatedClassList(tScope, appendable); + appendable.append("\n "); + appendable.append(CLOSING_BRACE); + appendable.append(END_LINE); + appendable.append(SINGLE_LINE_BREAK); + appendable.append(" "); + appendable.append(CLOSING_CURLY_BRACE); + appendable.append(SINGLE_LINE_BREAK); + } + + protected void appendTranslatedClassList(SimplTypesScope tScope, Appendable appendable) + throws IOException + { + List lines = new ArrayList(); + + Collection> allClasses = + tScope.entriesByClassName().values(); + for (ClassDescriptor oneClass : allClasses) + { + if (excludedClassNames.contains(oneClass)) + continue; + String packageName = oneClass.getDescribedClassPackageName(); + String namespace = nameTypeResolver.javaPackage2CSharpNamespace(packageName); + lines.add(String.format(",\n typeof(%s.%s%s)", + namespace, + oneClass.getDescribedClassSimpleName(), + oneClass.isGenericClass() ? "<>" : "")); + } + Collections.sort(lines); + for (String line : lines) + appendable.append(line); + } + + protected void appendDefaultConstructor(String className, Appendable appendable) + throws IOException + { + appendable.append("\n"); + appendable.append(String.format(" public %s()\n", className)); + appendable.append(" { }\n"); + } + +} diff --git a/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/ClassTranslatedEventHandler.java b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/ClassTranslatedEventHandler.java new file mode 100644 index 00000000..6ef955e0 --- /dev/null +++ b/simplTranslators/newsrc/ecologylab/simpl/translators/csharp/ClassTranslatedEventHandler.java @@ -0,0 +1,25 @@ +package ecologylab.simpl.translators.csharp; + +import java.util.Set; + +/** + * + * @author quyin + * + */ +public interface ClassTranslatedEventHandler +{ + + /** + * + * @param classNamespace + * @param classSimpleName + * @param classDef + * @param dependencies + */ + void classTranslated(String classNamespace, + String classSimpleName, + String classDef, + Set dependencies); + +} diff --git a/simplTranslators/resources/codeTranslators/javaCodeTranslator.stg b/simplTranslators/resources/codeTranslators/javaCodeTranslator.stg index dbb09be4..99c4f5e0 100644 --- a/simplTranslators/resources/codeTranslators/javaCodeTranslator.stg +++ b/simplTranslators/resources/codeTranslators/javaCodeTranslator.stg @@ -1,55 +1,55 @@ -delimiters "$", "$" - -name(x) ::= "$x.name$" - -elementType(fd) ::= "$fd.genericTypeVars; separator=\",\"$" - -listMethods(fd) ::= << - - - // lazy evaluation: - public List<$elementType(fd)$> $fd.name$() - { - if ($fd.name$ == null) - $fd.name$ = new ArrayList<$elementType(fd)$>(); - return $fd.name$; - } - - // addTo: - public void addTo$fd.name;format="capFirst"$($elementType(fd)$ element) - { - $fd.name$().add(element); - } - - // size: - public int $fd.name$Size() - { - return $fd.name$ == null ? 0 : $fd.name$.size(); - } - ->> - -mapMethods(fd) ::= << - - -// lazy evaluation: -public Map<$keyType$, $valueType$> $name$() -{ - if ($name$ == null) - $name$ = new HashMap<$keyType$, $valueType$>(); - return $name$; -} - -// putTo: -public void putTo$name;format="capFirst"$($keyType$ key, $valueType$ value) -{ - $name$().put(key, value); -} - -// size: -public int $name$Size() -{ - return $name$ == null ? 0 : $name$.size(); -} - ->> +delimiters "$", "$" + +name(x) ::= "$x.name$" + +elementType(fd) ::= "$fd.genericTypeVars; separator=\",\"$" + +listMethods(fd) ::= << + + + // lazy evaluation: + public List<$elementType(fd)$> $fd.name$() + { + if ($fd.name$ == null) + $fd.name$ = new ArrayList<$elementType(fd)$>(); + return $fd.name$; + } + + // addTo: + public void addTo$fd.name;format="capFirst"$($elementType(fd)$ element) + { + $fd.name$().add(element); + } + + // size: + public int $fd.name$Size() + { + return $fd.name$ == null ? 0 : $fd.name$.size(); + } + +>> + +mapMethods(fd) ::= << + + +// lazy evaluation: +public Map<$keyType$, $valueType$> $name$() +{ + if ($name$ == null) + $name$ = new HashMap<$keyType$, $valueType$>(); + return $name$; +} + +// putTo: +public void putTo$name;format="capFirst"$($keyType$ key, $valueType$ value) +{ + $name$().put(key, value); +} + +// size: +public int $name$Size() +{ + return $name$ == null ? 0 : $name$.size(); +} + +>> diff --git a/simplTranslators/src/ecologylab/translators/CodeTranslator.java b/simplTranslators/src/ecologylab/translators/CodeTranslator.java index 8a8f450c..367cc1b7 100644 --- a/simplTranslators/src/ecologylab/translators/CodeTranslator.java +++ b/simplTranslators/src/ecologylab/translators/CodeTranslator.java @@ -8,13 +8,13 @@ import ecologylab.serialization.SimplTypesScope; /** + * A general interface for translating code. * * @author quyin - * */ public interface CodeTranslator { - + /** * Generate source codes taking an input translation scope. *

@@ -22,33 +22,34 @@ public interface CodeTranslator * generate the required source codes. *

* - * @param directoryLocation + * @param destDir * The directory in which generated source codes will be placed. - * @param tScope + * @param typeScope * The translation scope from which source codes will be generated. * @param config - * The configuration. + * The configuration. * @throws IOException * @throws SIMPLTranslationException * @throws CodeTranslationException */ - void translate(File directoryLocation, SimplTypesScope tScope, CodeTranslatorConfig config) + void translate(File destDir, SimplTypesScope typeScope, CodeTranslatorConfig config) throws IOException, SIMPLTranslationException, CodeTranslationException; /** * Generates source codes taking an input {@link ClassDescriptor}. * - * @param classDescriptor - * The descriptor for the type that needs be to translated. - * @param directoryLocation + * @param destDir * The directory in which generated source codes will be placed. + * @param classToTranslate + * The descriptor for the type that needs be to translated. * @param config - * The configuration. + * The configuration. + * * @throws IOException * @throws CodeTranslationException */ - void translate(ClassDescriptor classDescriptor, File directoryLocation, CodeTranslatorConfig config) - throws IOException, CodeTranslationException; + void translate(File destDir, ClassDescriptor classToTranslate, CodeTranslatorConfig config) + throws IOException, SIMPLTranslationException, CodeTranslationException; /** * Exclude a class from translation. Useful for, e.g. excluding built-in classes. @@ -61,5 +62,5 @@ void translate(ClassDescriptor classDescriptor, File directoryLocation, CodeTran * @return The target language name. */ String getTargetLanguage(); - + } diff --git a/simplTranslators/src/ecologylab/translators/cocoa/library/package.html b/simplTranslators/src/ecologylab/translators/cocoa/library/package.html index b45a077b..dca3e6b7 100644 --- a/simplTranslators/src/ecologylab/translators/cocoa/library/package.html +++ b/simplTranslators/src/ecologylab/translators/cocoa/library/package.html @@ -1,3 +1,3 @@ - -A set of test classes to test the working cocoatranslator. - + +A set of test classes to test the working cocoatranslator. + diff --git a/simplTranslators/src/ecologylab/translators/cocoa/package.html b/simplTranslators/src/ecologylab/translators/cocoa/package.html index 3fe3dcf4..72a97614 100644 --- a/simplTranslators/src/ecologylab/translators/cocoa/package.html +++ b/simplTranslators/src/ecologylab/translators/cocoa/package.html @@ -1,3 +1,3 @@ - -A translator utility which can translate annotated java class files to objective-c header and implementation files. - + +A translator utility which can translate annotated java class files to objective-c header and implementation files. + diff --git a/simplTranslators/src/ecologylab/translators/java/JavaTranslator.java b/simplTranslators/src/ecologylab/translators/java/JavaTranslator.java index dcc06577..b7627572 100644 --- a/simplTranslators/src/ecologylab/translators/java/JavaTranslator.java +++ b/simplTranslators/src/ecologylab/translators/java/JavaTranslator.java @@ -88,7 +88,7 @@ public class JavaTranslator extends AbstractCodeTranslator implements JavaTransl String template = sb.toString(); templateGroup = new STGroupString(template); - templateGroup.registerRenderer(String.class, new AttributeRenderer() + AttributeRenderer attributeRenderer = new AttributeRenderer() { @Override public String toString(Object o, String formatString, Locale locale) @@ -102,7 +102,8 @@ public String toString(Object o, String formatString, Locale locale) return s; } - }); + }; + templateGroup.registerRenderer(String.class, attributeRenderer); } /** @@ -164,14 +165,14 @@ public void translate(File directoryLocation, SimplTypesScope tScope, CodeTransl debug("Excluding " + classDesc + " from translation as requested"); continue; } - translate(classDesc, directoryLocation, config); + translate(directoryLocation, classDesc, config); } generateLibraryTScopeClass(directoryLocation, tScope, config.getLibraryTScopeClassPackage(), config.getLibraryTScopeClassSimpleName()); System.out.println("DONE !"); } @Override - public void translate(ClassDescriptor inputClass, File directoryLocation, CodeTranslatorConfig config) + public void translate(File destDir, ClassDescriptor inputClass, CodeTranslatorConfig config) throws IOException, JavaTranslationException { String packageName = inputClass.getDescribedClassPackageName(); @@ -181,7 +182,7 @@ public void translate(ClassDescriptor inputClass, File directoryLocation, CodeTr if (this.typesScopeName == null) this.typesScopeName = packageName + "." + classSimpleName + "_simpl_types_scope"; File outputFile = createFileWithDirStructure( - directoryLocation, + destDir, packageName.split(PACKAGE_NAME_SEPARATOR), classSimpleName, FILE_EXTENSION diff --git a/simplTranslators/src/ecologylab/translators/javascript/test/Bank.java b/simplTranslators/src/ecologylab/translators/javascript/test/Bank.java index 489ed73b..53237e6f 100644 --- a/simplTranslators/src/ecologylab/translators/javascript/test/Bank.java +++ b/simplTranslators/src/ecologylab/translators/javascript/test/Bank.java @@ -1,27 +1,27 @@ -package ecologylab.translators.javascript.test; - -import java.util.HashMap; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_map; -import ecologylab.serialization.annotations.simpl_map_key_field; -import ecologylab.serialization.annotations.simpl_nowrap; - -public class Bank extends ElementState{ - @simpl_nowrap - @simpl_map("items") - @simpl_map_key_field("ownerName") - HashMap itemMap; - // - //@simpl_map("item") - //@simpl_map_key_field("id") - //Map items; - // - // - // - - public Bank(HashMap itemMap) { - super(); - this.itemMap = itemMap; - } -} +package ecologylab.translators.javascript.test; + +import java.util.HashMap; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_map; +import ecologylab.serialization.annotations.simpl_map_key_field; +import ecologylab.serialization.annotations.simpl_nowrap; + +public class Bank extends ElementState{ + @simpl_nowrap + @simpl_map("items") + @simpl_map_key_field("ownerName") + HashMap itemMap; + // + //@simpl_map("item") + //@simpl_map_key_field("id") + //Map items; + // + // + // + + public Bank(HashMap itemMap) { + super(); + this.itemMap = itemMap; + } +} diff --git a/simplTranslators/src/ecologylab/translators/javascript/test/Computer.java b/simplTranslators/src/ecologylab/translators/javascript/test/Computer.java index 9cca6e11..5d2dc78d 100644 --- a/simplTranslators/src/ecologylab/translators/javascript/test/Computer.java +++ b/simplTranslators/src/ecologylab/translators/javascript/test/Computer.java @@ -1,16 +1,16 @@ -package ecologylab.translators.javascript.test; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -public @simpl_inherit class Computer extends Player { - @simpl_scalar float difficulty; - public Computer(float difficulty, String type, String ai,String name, int strength, int speed, int skin) { - super( name, strength, speed, skin); - this.difficulty = difficulty; - this.type = type; - this.ai = ai; - } - @simpl_scalar String type; - @simpl_scalar String ai; -} +package ecologylab.translators.javascript.test; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +public @simpl_inherit class Computer extends Player { + @simpl_scalar float difficulty; + public Computer(float difficulty, String type, String ai,String name, int strength, int speed, int skin) { + super( name, strength, speed, skin); + this.difficulty = difficulty; + this.type = type; + this.ai = ai; + } + @simpl_scalar String type; + @simpl_scalar String ai; +} diff --git a/simplTranslators/src/ecologylab/translators/javascript/test/Human.java b/simplTranslators/src/ecologylab/translators/javascript/test/Human.java index ae7a5617..2e0fb1a0 100644 --- a/simplTranslators/src/ecologylab/translators/javascript/test/Human.java +++ b/simplTranslators/src/ecologylab/translators/javascript/test/Human.java @@ -1,17 +1,17 @@ -package ecologylab.translators.javascript.test; - -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_scalar; - -@simpl_inherit -public class Human extends Player { - @simpl_scalar int rank; - public Human(int rank, int level, float cash, String name, int strength, int speed, int skin) { - super( name, strength, speed, skin); - this.rank = rank; - this.level = level; - this.cash = cash; - } - @simpl_scalar int level; - @simpl_scalar float cash; -} +package ecologylab.translators.javascript.test; + +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_scalar; + +@simpl_inherit +public class Human extends Player { + @simpl_scalar int rank; + public Human(int rank, int level, float cash, String name, int strength, int speed, int skin) { + super( name, strength, speed, skin); + this.rank = rank; + this.level = level; + this.cash = cash; + } + @simpl_scalar int level; + @simpl_scalar float cash; +} diff --git a/simplTranslators/src/ecologylab/translators/javascript/test/Item.java b/simplTranslators/src/ecologylab/translators/javascript/test/Item.java index 6fc78278..aeaade0e 100644 --- a/simplTranslators/src/ecologylab/translators/javascript/test/Item.java +++ b/simplTranslators/src/ecologylab/translators/javascript/test/Item.java @@ -1,16 +1,16 @@ -package ecologylab.translators.javascript.test; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -public class Item extends ElementState{ - @simpl_scalar float price; - @simpl_scalar String ownerName; - @simpl_scalar String name; - public Item(float price, String ownerName, String name) { - super(); - this.price = price; - this.ownerName = ownerName; - this.name = name; - } -} +package ecologylab.translators.javascript.test; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +public class Item extends ElementState{ + @simpl_scalar float price; + @simpl_scalar String ownerName; + @simpl_scalar String name; + public Item(float price, String ownerName, String name) { + super(); + this.price = price; + this.ownerName = ownerName; + this.name = name; + } +} diff --git a/simplTranslators/src/ecologylab/translators/javascript/test/Move.java b/simplTranslators/src/ecologylab/translators/javascript/test/Move.java index d35aaa9b..dbfcca04 100644 --- a/simplTranslators/src/ecologylab/translators/javascript/test/Move.java +++ b/simplTranslators/src/ecologylab/translators/javascript/test/Move.java @@ -1,21 +1,21 @@ -package ecologylab.translators.javascript.test; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_scalar; - -public class Move extends ElementState{ - @simpl_scalar float x; - @simpl_scalar float y; - @simpl_scalar boolean sneaking; - @simpl_scalar boolean defending; - @simpl_scalar float moveTime; - public Move(float x, float y, boolean sneaking, boolean defending, - float moveTime) { - super(); - this.x = x; - this.y = y; - this.sneaking = sneaking; - this.defending = defending; - this.moveTime = moveTime; - } -} +package ecologylab.translators.javascript.test; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_scalar; + +public class Move extends ElementState{ + @simpl_scalar float x; + @simpl_scalar float y; + @simpl_scalar boolean sneaking; + @simpl_scalar boolean defending; + @simpl_scalar float moveTime; + public Move(float x, float y, boolean sneaking, boolean defending, + float moveTime) { + super(); + this.x = x; + this.y = y; + this.sneaking = sneaking; + this.defending = defending; + this.moveTime = moveTime; + } +} diff --git a/simplTranslators/src/ecologylab/translators/javascript/test/Movements.java b/simplTranslators/src/ecologylab/translators/javascript/test/Movements.java index 3651ffd2..246379d8 100644 --- a/simplTranslators/src/ecologylab/translators/javascript/test/Movements.java +++ b/simplTranslators/src/ecologylab/translators/javascript/test/Movements.java @@ -1,19 +1,19 @@ -package ecologylab.translators.javascript.test; - -import java.util.ArrayList; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; - -public class Movements extends ElementState { - @simpl_scalar float time; - @simpl_nowrap - @simpl_collection("moves") ArrayList moves; - public Movements(float time, ArrayList moves) { - super(); - this.time = time; - this.moves = moves; - } -} +package ecologylab.translators.javascript.test; + +import java.util.ArrayList; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; + +public class Movements extends ElementState { + @simpl_scalar float time; + @simpl_nowrap + @simpl_collection("moves") ArrayList moves; + public Movements(float time, ArrayList moves) { + super(); + this.time = time; + this.moves = moves; + } +} diff --git a/simplTranslators/src/ecologylab/translators/javascript/test/ReferToSelf.java b/simplTranslators/src/ecologylab/translators/javascript/test/ReferToSelf.java index cff69733..893bb01a 100644 --- a/simplTranslators/src/ecologylab/translators/javascript/test/ReferToSelf.java +++ b/simplTranslators/src/ecologylab/translators/javascript/test/ReferToSelf.java @@ -1,25 +1,25 @@ -package ecologylab.translators.javascript.test; - -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_scalar; - -public class ReferToSelf extends ElementState -{ - @simpl_scalar - String someData; - - @simpl_composite - ReferToSelf referenceToSelf; - - public ReferToSelf() - { - someData = "I have a null for referenceToSelf"; - referenceToSelf = null; - } - public ReferToSelf(int num) - { - someData = "I have a null for referenceToSelf"; - referenceToSelf = this; - } -} +package ecologylab.translators.javascript.test; + +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_scalar; + +public class ReferToSelf extends ElementState +{ + @simpl_scalar + String someData; + + @simpl_composite + ReferToSelf referenceToSelf; + + public ReferToSelf() + { + someData = "I have a null for referenceToSelf"; + referenceToSelf = null; + } + public ReferToSelf(int num) + { + someData = "I have a null for referenceToSelf"; + referenceToSelf = this; + } +} diff --git a/simplTranslators/src/ecologylab/translators/net/DotNetTranslationConstants.java b/simplTranslators/src/ecologylab/translators/net/DotNetTranslationConstants.java index 3e697601..180b76f4 100644 --- a/simplTranslators/src/ecologylab/translators/net/DotNetTranslationConstants.java +++ b/simplTranslators/src/ecologylab/translators/net/DotNetTranslationConstants.java @@ -1,178 +1,178 @@ -package ecologylab.translators.net; - -import ecologylab.serialization.SimplTypesScope; - -/** - * General class file declares various constants used by the translators for generating the right - * output files. - * - * @author Nabeel Shahzad - */ -public interface DotNetTranslationConstants -{ - - /* - * File constants - */ - public static final String PACKAGE_NAME_SEPARATOR = "\\."; - - public static final String FILE_PATH_SEPARATOR = "/"; - - public static final String FILE_EXTENSION = ".cs"; - - public static final String XML_FILE_EXTENSION = ".xml"; - - public static final String TRANSATIONSCOPE_FOLDER = "tscope"; - - /* - * Keywords - */ - public static final String PUBLIC = "public"; - - public static final String STATIC = "static"; - - public static final String PRIVATE = "private"; - - public static final String GET = "get"; - - public static final String SET = "set"; - - public static final String CLASS = "class"; - - public static final String RETURN = "return"; - - public static final String VALUE = "value"; - - public static final String INHERITANCE_OBJECT = "ElementState"; - - public static final String INHERITANCE_OPERATOR = ":"; - - public static final String NAMESPACE = "namespace"; - - public static final String USING = "using"; - - public static final String SYSTEM = "System"; - - public static final String COLLECTIONS = "Collections"; - - public static final String GENERIC = "Generic"; - - public static final String ECOLOGYLAB_NAMESPACE = "ecologylab.attributes"; - - public static final String SERIALIZATION_NAMESPACE = "ecologylab.serialization"; - - public static final String KEY = "key"; - - public static final String TYPE_OF = "typeof"; - - public static final String DEFAULT_IMPLEMENTATION = "throw new NotImplementedException();"; - - /* - * Formatting constants - */ - - public static final String OPENING_CURLY_BRACE = "{"; - - public static final String CLOSING_CURLY_BRACE = "}"; - - public static final String OPENING_SQUARE_BRACE = "["; - - public static final String CLOSING_SQUARE_BRACE = "]"; - - public static final String OPENING_BRACE = "("; - - public static final String CLOSING_BRACE = ")"; - - public static final String SINGLE_LINE_BREAK = "\n"; - - public static final String DOUBLE_LINE_BREAK = "\n\n"; - - public static final String TAB = "\t"; - - public static final String DOUBLE_TAB = "\t\t"; - - public static final String SPACE = " "; - - public static final String DOT = "."; - - public static final String QUOTE = "\""; - - public static final String COMMA = ","; - - public static final String END_LINE = ";"; - - public static final String ASSIGN = "="; - - public static final String OPEN_COMMENTS = "/// "; - - public static final String XML_COMMENTS = "/// "; - - public static final String CLOSE_COMMENTS = "/// "; - - public static final String SINGLE_LINE_COMMENT = "//"; - - public static final String OPEN_BLOCK_COMMENTS = "/*"; - - public static final String CLOSE_BLOCK_COMMENTS = "*/"; - - /* - * Scalar types - */ - public static final String DOTNET_INTEGER = "Int32"; - - public static final String DOTNET_FLOAT = "Single"; - - public static final String DOTNET_DOUBLE = "Double"; - - public static final String DOTNET_BYTE = "Char"; - - public static final String DOTNET_CHAR = "Byte"; - - public static final String DOTNET_BOOLEAN = "Boolean"; - - public static final String DOTNET_LONG = "Int64"; - - public static final String DOTNET_SHORT = "Int16"; - - public static final String DOTNET_STRING = "String"; - - /* - * Reference types - */ - public static final String DOTNET_DATE = "DateTime"; - - public static final String DOTNET_STRING_BUILDER = "StringBuilder"; - - public static final String DOTNET_URL = "Uri"; - - public static final String DOTNET_PARSED_URL = "ParsedURL"; - - public static final String DOTNET_SCALAR_TYPE = "ScalarType"; - - public static final String DOTNET_CLASS = "Type"; - - public static final String DOTNET_FIELD = "FieldInfo"; - - public static final String DOTNET_OBJECT = "Object"; - - public static final String DOTNET_TRANSLATION_SCOPE = SimplTypesScope.class.getSimpleName(); - - /* - * Collection types - */ - public static final String DOTNET_ARRAYLIST = "List"; - - public static final String DOTNET_HASHMAP = "Dictionary"; - - public static final String DOTNET_HASHMAPARRAYLIST = "DictionaryList"; - - public static final String DOTNET_SCOPE = "Scope"; - - /* - * Other constants - */ - public static final String FGET = "Get"; - - public static final String NEW_OP = "new"; - -} +package ecologylab.translators.net; + +import ecologylab.serialization.SimplTypesScope; + +/** + * General class file declares various constants used by the translators for generating the right + * output files. + * + * @author Nabeel Shahzad + */ +public interface DotNetTranslationConstants +{ + + /* + * File constants + */ + public static final String PACKAGE_NAME_SEPARATOR = "\\."; + + public static final String FILE_PATH_SEPARATOR = "/"; + + public static final String FILE_EXTENSION = ".cs"; + + public static final String XML_FILE_EXTENSION = ".xml"; + + public static final String TRANSATIONSCOPE_FOLDER = "tscope"; + + /* + * Keywords + */ + public static final String PUBLIC = "public"; + + public static final String STATIC = "static"; + + public static final String PRIVATE = "private"; + + public static final String GET = "get"; + + public static final String SET = "set"; + + public static final String CLASS = "class"; + + public static final String RETURN = "return"; + + public static final String VALUE = "value"; + + public static final String INHERITANCE_OBJECT = "ElementState"; + + public static final String INHERITANCE_OPERATOR = ":"; + + public static final String NAMESPACE = "namespace"; + + public static final String USING = "using"; + + public static final String SYSTEM = "System"; + + public static final String COLLECTIONS = "Collections"; + + public static final String GENERIC = "Generic"; + + public static final String ECOLOGYLAB_NAMESPACE = "ecologylab.attributes"; + + public static final String SERIALIZATION_NAMESPACE = "ecologylab.serialization"; + + public static final String KEY = "key"; + + public static final String TYPE_OF = "typeof"; + + public static final String DEFAULT_IMPLEMENTATION = "throw new NotImplementedException();"; + + /* + * Formatting constants + */ + + public static final String OPENING_CURLY_BRACE = "{"; + + public static final String CLOSING_CURLY_BRACE = "}"; + + public static final String OPENING_SQUARE_BRACE = "["; + + public static final String CLOSING_SQUARE_BRACE = "]"; + + public static final String OPENING_BRACE = "("; + + public static final String CLOSING_BRACE = ")"; + + public static final String SINGLE_LINE_BREAK = "\n"; + + public static final String DOUBLE_LINE_BREAK = "\n\n"; + + public static final String TAB = "\t"; + + public static final String DOUBLE_TAB = "\t\t"; + + public static final String SPACE = " "; + + public static final String DOT = "."; + + public static final String QUOTE = "\""; + + public static final String COMMA = ","; + + public static final String END_LINE = ";"; + + public static final String ASSIGN = "="; + + public static final String OPEN_COMMENTS = "/// "; + + public static final String XML_COMMENTS = "/// "; + + public static final String CLOSE_COMMENTS = "/// "; + + public static final String SINGLE_LINE_COMMENT = "//"; + + public static final String OPEN_BLOCK_COMMENTS = "/*"; + + public static final String CLOSE_BLOCK_COMMENTS = "*/"; + + /* + * Scalar types + */ + public static final String DOTNET_INTEGER = "Int32"; + + public static final String DOTNET_FLOAT = "Single"; + + public static final String DOTNET_DOUBLE = "Double"; + + public static final String DOTNET_BYTE = "Char"; + + public static final String DOTNET_CHAR = "Byte"; + + public static final String DOTNET_BOOLEAN = "Boolean"; + + public static final String DOTNET_LONG = "Int64"; + + public static final String DOTNET_SHORT = "Int16"; + + public static final String DOTNET_STRING = "String"; + + /* + * Reference types + */ + public static final String DOTNET_DATE = "DateTime"; + + public static final String DOTNET_STRING_BUILDER = "StringBuilder"; + + public static final String DOTNET_URL = "Uri"; + + public static final String DOTNET_PARSED_URL = "ParsedURL"; + + public static final String DOTNET_SCALAR_TYPE = "ScalarType"; + + public static final String DOTNET_CLASS = "Type"; + + public static final String DOTNET_FIELD = "FieldInfo"; + + public static final String DOTNET_OBJECT = "Object"; + + public static final String DOTNET_TRANSLATION_SCOPE = SimplTypesScope.class.getSimpleName(); + + /* + * Collection types + */ + public static final String DOTNET_ARRAYLIST = "List"; + + public static final String DOTNET_HASHMAP = "Dictionary"; + + public static final String DOTNET_HASHMAPARRAYLIST = "DictionaryList"; + + public static final String DOTNET_SCOPE = "Scope"; + + /* + * Other constants + */ + public static final String FGET = "Get"; + + public static final String NEW_OP = "new"; + +} diff --git a/simplTranslators/src/ecologylab/translators/net/DotNetTranslationUtilities.java b/simplTranslators/src/ecologylab/translators/net/DotNetTranslationUtilities.java index bd6de5ab..5db2cfe0 100644 --- a/simplTranslators/src/ecologylab/translators/net/DotNetTranslationUtilities.java +++ b/simplTranslators/src/ecologylab/translators/net/DotNetTranslationUtilities.java @@ -1,206 +1,206 @@ -package ecologylab.translators.net; - -import java.util.HashMap; -import java.util.Map; - -import ecologylab.generic.StringBuilderBaseUtils; -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.XMLTools; - -/** - * Static methods to do repeated useful tasks during the translation - * - * - * @author nabeel - * - */ -public class DotNetTranslationUtilities -{ - - private static final String PROPERTY_SAFE_SUFFIX = "Prop"; - - private static final String BAD_NAME = "### BAD NAME ###"; - - private static HashMap keywords = new HashMap(); - - static - { - keywords.put("object", "object"); - keywords.put("as", "as"); - keywords.put("byte", "byte"); - keywords.put("class", "class"); - keywords.put("delegate", "delegate"); - keywords.put("event", "event"); - keywords.put("fixed", "fixed"); - keywords.put("goto", "goto"); - keywords.put("interface", "interface"); - keywords.put("namespace", "namespace"); - keywords.put("out", "out"); - keywords.put("public", "public"); - keywords.put("sealed", "sealed"); - keywords.put("static", "static"); - keywords.put("throw", "throw"); - keywords.put("ulong", "ulong"); - keywords.put("var", "var"); - keywords.put("case", "case"); - keywords.put("const", "const"); - keywords.put("do", "do"); - keywords.put("explicit", "explicit"); - keywords.put("float", "float"); - keywords.put("if", "if"); - keywords.put("internal", "internal"); - keywords.put("new", "new"); - keywords.put("override", "override"); - keywords.put("readonly", "readonly"); - keywords.put("short", "short"); - keywords.put("string", "string"); - keywords.put("true", "true"); - keywords.put("unchecked", "unchecked"); - keywords.put("virtual", "virtual"); - keywords.put("base", "base"); - keywords.put("catch", "catch"); - keywords.put("continue", "continue"); - keywords.put("double", "double"); - keywords.put("extern", "extern"); - keywords.put("for", "for"); - keywords.put("implicit", "implicit"); - keywords.put("is", "is"); - keywords.put("null", "null"); - keywords.put("params", "params"); - keywords.put("ref", "ref"); - keywords.put("sizeof", "sizeof"); - keywords.put("struct", "struct"); - keywords.put("try", "try"); - keywords.put("unsafe", "unsafe"); - keywords.put("void", "void"); - keywords.put("bool", "bool"); - keywords.put("char", "char"); - keywords.put("decimal", "decimal"); - keywords.put("else", "else"); - keywords.put("false", "false"); - keywords.put("foreach", "foreach"); - keywords.put("in", "in"); - keywords.put("lock", "lock"); - keywords.put("private", "private"); - keywords.put("return", "return"); - keywords.put("stackalloc", "return"); - keywords.put("switch", "switch"); - keywords.put("typeof", "typeof"); - keywords.put("ushort", "ushort"); - keywords.put("volatile", "volatile"); - keywords.put("break", "break"); - keywords.put("checked", "checked"); - keywords.put("default", "default"); - keywords.put("enum", "enum"); - keywords.put("finally", "finally"); - keywords.put("int", "int"); - keywords.put("long", "long"); - keywords.put("operator", "operator"); - keywords.put("protected", "protected"); - keywords.put("sbyte", "sbyte"); - keywords.put("this", "this"); - keywords.put("uint", "uint"); - keywords.put("using", "using"); - keywords.put("while", "while"); - } - - /** - * Utility mehthods to check if the given field name is a keyword in objective-c - * - * @param fieldName - */ - public static boolean isKeyword(String fieldName) - { - return keywords.containsKey(fieldName); - } - - /** - * (Potentially) The look-up table for translating Java annotations to C# attributes. Only for - * those not conforming with the standard translation method. - */ - private static Map annotationTranslations = new HashMap(); - - private static Map annotationPackageTranslations = new HashMap(); - - static - { - // init annotationTranslations - annotationTranslations.put("simpl_nowrap", "SimplNoWrap"); - - // init annotationNamespaceTranslations - annotationPackageTranslations.put("ecologylab.serialization.annotations", BAD_NAME); - } - - /** - * Utility function to translate java annotation names to C# attribute names. - * - * If there is an entry in the translation table, use that entry; otherwise use camel case. - * - * @param annotation - * @return - */ - public static String translateAnnotationName(String simpleName) - { - if (annotationTranslations.containsKey(simpleName)) - return annotationTranslations.get(simpleName); - return XMLTools.classNameFromElementName(simpleName); - } - - /** - * Utility function to translate java annotation package names to C# namespaces. - * - * If there is an entry in the translation table, and the value is BAD_NAME, return null; - * - * If there is an entry in the translation table but the value is not BAD_NAME, use that entry; - * - * If there is no entry in the translation table, return the original package name. - * - * @param packageName - * @return - */ - public static String translateAnnotationPackage(String packageName) - { - String translatedNamespace = annotationPackageTranslations.get(packageName); - if (BAD_NAME.equals(translatedNamespace)) - return null; - else - return translatedNamespace == null ? packageName : translatedNamespace; - } - - /** - * Generate a C# property name for this field. - * @param context TODO - * @param fieldDescriptor - * - * @return - */ - public static String getPropertyName(ClassDescriptor context, FieldDescriptor fieldDescriptor) - { - String fieldName = fieldDescriptor.getName(); - - StringBuilder propertyNameBuilder = StringBuilderBaseUtils.acquire(); - String propertyName = null; - String declaringClassName = context.getDescribedClassSimpleName(); - if (Character.isLowerCase(fieldName.charAt(0))) - { - propertyNameBuilder.append(Character.toUpperCase(fieldName.charAt(0))); - propertyNameBuilder.append(fieldName, 1, fieldName.length()); - propertyName = propertyNameBuilder.toString(); - if (propertyName.equals(declaringClassName)) - { - propertyNameBuilder.append(PROPERTY_SAFE_SUFFIX); - propertyName = propertyNameBuilder.toString(); - } - } - else - { - propertyNameBuilder.append(fieldName); - propertyNameBuilder.append(PROPERTY_SAFE_SUFFIX); - propertyName = propertyNameBuilder.toString(); - } - StringBuilderBaseUtils.release(propertyNameBuilder); - return propertyName; - } - -} +package ecologylab.translators.net; + +import java.util.HashMap; +import java.util.Map; + +import ecologylab.generic.StringBuilderBaseUtils; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.XMLTools; + +/** + * Static methods to do repeated useful tasks during the translation + * + * + * @author nabeel + * + */ +public class DotNetTranslationUtilities +{ + + private static final String PROPERTY_SAFE_SUFFIX = "Prop"; + + private static final String BAD_NAME = "### BAD NAME ###"; + + private static HashMap keywords = new HashMap(); + + static + { + keywords.put("object", "object"); + keywords.put("as", "as"); + keywords.put("byte", "byte"); + keywords.put("class", "class"); + keywords.put("delegate", "delegate"); + keywords.put("event", "event"); + keywords.put("fixed", "fixed"); + keywords.put("goto", "goto"); + keywords.put("interface", "interface"); + keywords.put("namespace", "namespace"); + keywords.put("out", "out"); + keywords.put("public", "public"); + keywords.put("sealed", "sealed"); + keywords.put("static", "static"); + keywords.put("throw", "throw"); + keywords.put("ulong", "ulong"); + keywords.put("var", "var"); + keywords.put("case", "case"); + keywords.put("const", "const"); + keywords.put("do", "do"); + keywords.put("explicit", "explicit"); + keywords.put("float", "float"); + keywords.put("if", "if"); + keywords.put("internal", "internal"); + keywords.put("new", "new"); + keywords.put("override", "override"); + keywords.put("readonly", "readonly"); + keywords.put("short", "short"); + keywords.put("string", "string"); + keywords.put("true", "true"); + keywords.put("unchecked", "unchecked"); + keywords.put("virtual", "virtual"); + keywords.put("base", "base"); + keywords.put("catch", "catch"); + keywords.put("continue", "continue"); + keywords.put("double", "double"); + keywords.put("extern", "extern"); + keywords.put("for", "for"); + keywords.put("implicit", "implicit"); + keywords.put("is", "is"); + keywords.put("null", "null"); + keywords.put("params", "params"); + keywords.put("ref", "ref"); + keywords.put("sizeof", "sizeof"); + keywords.put("struct", "struct"); + keywords.put("try", "try"); + keywords.put("unsafe", "unsafe"); + keywords.put("void", "void"); + keywords.put("bool", "bool"); + keywords.put("char", "char"); + keywords.put("decimal", "decimal"); + keywords.put("else", "else"); + keywords.put("false", "false"); + keywords.put("foreach", "foreach"); + keywords.put("in", "in"); + keywords.put("lock", "lock"); + keywords.put("private", "private"); + keywords.put("return", "return"); + keywords.put("stackalloc", "return"); + keywords.put("switch", "switch"); + keywords.put("typeof", "typeof"); + keywords.put("ushort", "ushort"); + keywords.put("volatile", "volatile"); + keywords.put("break", "break"); + keywords.put("checked", "checked"); + keywords.put("default", "default"); + keywords.put("enum", "enum"); + keywords.put("finally", "finally"); + keywords.put("int", "int"); + keywords.put("long", "long"); + keywords.put("operator", "operator"); + keywords.put("protected", "protected"); + keywords.put("sbyte", "sbyte"); + keywords.put("this", "this"); + keywords.put("uint", "uint"); + keywords.put("using", "using"); + keywords.put("while", "while"); + } + + /** + * Utility mehthods to check if the given field name is a keyword in objective-c + * + * @param fieldName + */ + public static boolean isKeyword(String fieldName) + { + return keywords.containsKey(fieldName); + } + + /** + * (Potentially) The look-up table for translating Java annotations to C# attributes. Only for + * those not conforming with the standard translation method. + */ + private static Map annotationTranslations = new HashMap(); + + private static Map annotationPackageTranslations = new HashMap(); + + static + { + // init annotationTranslations + annotationTranslations.put("simpl_nowrap", "SimplNoWrap"); + + // init annotationNamespaceTranslations + annotationPackageTranslations.put("ecologylab.serialization.annotations", BAD_NAME); + } + + /** + * Utility function to translate java annotation names to C# attribute names. + * + * If there is an entry in the translation table, use that entry; otherwise use camel case. + * + * @param annotation + * @return + */ + public static String translateAnnotationName(String simpleName) + { + if (annotationTranslations.containsKey(simpleName)) + return annotationTranslations.get(simpleName); + return XMLTools.classNameFromElementName(simpleName); + } + + /** + * Utility function to translate java annotation package names to C# namespaces. + * + * If there is an entry in the translation table, and the value is BAD_NAME, return null; + * + * If there is an entry in the translation table but the value is not BAD_NAME, use that entry; + * + * If there is no entry in the translation table, return the original package name. + * + * @param packageName + * @return + */ + public static String translateAnnotationPackage(String packageName) + { + String translatedNamespace = annotationPackageTranslations.get(packageName); + if (BAD_NAME.equals(translatedNamespace)) + return null; + else + return translatedNamespace == null ? packageName : translatedNamespace; + } + + /** + * Generate a C# property name for this field. + * @param context TODO + * @param fieldDescriptor + * + * @return + */ + public static String getPropertyName(ClassDescriptor context, FieldDescriptor fieldDescriptor) + { + String fieldName = fieldDescriptor.getName(); + + StringBuilder propertyNameBuilder = StringBuilderBaseUtils.acquire(); + String propertyName = null; + String declaringClassName = context.getDescribedClassSimpleName(); + if (Character.isLowerCase(fieldName.charAt(0))) + { + propertyNameBuilder.append(Character.toUpperCase(fieldName.charAt(0))); + propertyNameBuilder.append(fieldName, 1, fieldName.length()); + propertyName = propertyNameBuilder.toString(); + if (propertyName.equals(declaringClassName)) + { + propertyNameBuilder.append(PROPERTY_SAFE_SUFFIX); + propertyName = propertyNameBuilder.toString(); + } + } + else + { + propertyNameBuilder.append(fieldName); + propertyNameBuilder.append(PROPERTY_SAFE_SUFFIX); + propertyName = propertyNameBuilder.toString(); + } + StringBuilderBaseUtils.release(propertyNameBuilder); + return propertyName; + } + +} diff --git a/simplTranslators/src/ecologylab/translators/net/DotNetTranslator.java b/simplTranslators/src/ecologylab/translators/net/DotNetTranslator.java index 04518b2e..d2bddf27 100644 --- a/simplTranslators/src/ecologylab/translators/net/DotNetTranslator.java +++ b/simplTranslators/src/ecologylab/translators/net/DotNetTranslator.java @@ -64,10 +64,14 @@ public class DotNetTranslator extends AbstractCodeTranslator implements DotNetTr protected CodeTranslatorConfig config; + private Set classSimpleNames; + public DotNetTranslator() { super("csharp"); + classSimpleNames = new HashSet(); + addGlobalDependency("System"); addGlobalDependency("System.Collections"); addGlobalDependency("System.Collections.Generic"); @@ -85,13 +89,17 @@ public void translate(File directoryLocation, SimplTypesScope tScope, CodeTransl this.config = config; Collection> classes = tScope.entriesByClassName().values(); for (ClassDescriptor classDesc : classes) + { + classSimpleNames.add(classDesc.getDescribedClassSimpleName()); + } + for (ClassDescriptor classDesc : classes) { if (excludeClassesFromTranslation.contains(classDesc)) { debug("Excluding " + classDesc + "from translation as requested."); continue; } - translate(classDesc, directoryLocation, config); + translate(directoryLocation, classDesc, config); } String libraryTScopeNamespace = javaPackage2CSharpNamespace(config.getLibraryTScopeClassPackage()); generateLibraryTScopeClass(directoryLocation, tScope, libraryTScopeNamespace, config.getLibraryTScopeClassSimpleName()); @@ -99,13 +107,13 @@ public void translate(File directoryLocation, SimplTypesScope tScope, CodeTransl } @Override - public void translate(ClassDescriptor inputClass, File directoryLocation, CodeTranslatorConfig config) + public void translate(File destDir, ClassDescriptor inputClass, CodeTranslatorConfig config) throws IOException, DotNetTranslationException { debug("Generating C# class: " + inputClass.getDescribedClassName() + "..."); this.config = config; File outputFile = createFileWithDirStructure( - directoryLocation, + destDir, getGeneratedClassFileDirStructure(inputClass), inputClass.getDescribedClassSimpleName(), FILE_EXTENSION @@ -114,6 +122,16 @@ public void translate(ClassDescriptor inputClass, File directoryLocation, CodeTr translate(inputClass, implementMappableInterface, bufferedWriter); bufferedWriter.close(); debug("done."); + } + + protected Set getClassSimpleNames() + { + return classSimpleNames; + } + + protected boolean isSimpleClassName(String name) + { + return classSimpleNames != null && classSimpleNames.contains(name); } protected String[] getGeneratedClassFileDirStructure(ClassDescriptor inputClass) diff --git a/simplTranslators/src/ecologylab/translators/net/package.html b/simplTranslators/src/ecologylab/translators/net/package.html index 86e8d8a8..34c6025a 100644 --- a/simplTranslators/src/ecologylab/translators/net/package.html +++ b/simplTranslators/src/ecologylab/translators/net/package.html @@ -1,3 +1,3 @@ - -A translator utility which can translate annotated java class files to dot net class files. + +A translator utility which can translate annotated java class files to dot net class files. \ No newline at end of file diff --git a/simplTranslators/src/ecologylab/translators/parser/FileTraversal.java b/simplTranslators/src/ecologylab/translators/parser/FileTraversal.java index 3f88c1d1..1d97395c 100644 --- a/simplTranslators/src/ecologylab/translators/parser/FileTraversal.java +++ b/simplTranslators/src/ecologylab/translators/parser/FileTraversal.java @@ -1,138 +1,138 @@ -package ecologylab.translators.parser; - -import java.io.File; -import java.io.IOException; - -import ecologylab.serialization.ElementState; - -/** - * Class file to search for java source files. Using the Class type objects this class searches for - * source files inside a root directory recursively. This class is being used by the JavaDocParser - * to fetch java doc comments from source files. - * - * @author nabeel - */ -public class FileTraversal -{ - /** - * Object which persists during recursive file search. - */ - private File searchedFile = null; - - /** - * inputClass which is set when searching for the file. - */ - private Class inputClass; - - /** - * Default constructor. does nothing - */ - public FileTraversal() - { - - } - - /** - * Searches for a given inside a root directory. - * - * @param thatClass - * @param rootLocation - * @return File null if the search did not yield any result. - * @throws IOException - */ - public File searchForFile(Class thatClass, File rootLocation) - throws IOException - { - this.searchedFile = null; - this.inputClass = thatClass; - this.traverse(rootLocation); - - return searchedFile; - } - - /** - * Returns the search file. Use - * File searchForFile(Class thatClass, File rootLocation) - * before using this method. If this value is null than the file was not found. - * - * @return File - */ - public File getSearchedFile() - { - return searchedFile; - } - - /** - * Recursive method to traverse through each file in the root directory. - * - * @param file - * @throws IOException - */ - private final void traverse(final File file) throws IOException - { - if (file.isDirectory()) - { - onDirectory(file); - final File[] childs = file.listFiles(); - for (File child : childs) - { - traverse(child); - } - return; - } - onFile(file); - } - - /** - * This method is invoked if the search passes through a directory. - * - * @param directory - */ - private void onDirectory(final File directory) - { - } - - /** - * This method is invoked if the search passes through a file. - * - * @param targetFile - */ - private void onFile(final File targetFile) - { - if (targetFile.getName().equals(inputClass.getSimpleName() + ".java")) - if (belongsToSamePackage(inputClass, targetFile)) - searchedFile = targetFile; - } - - /** - * Utility method to check if the found source file also belongs to the same package as input - * class. - * - * @param thatClass - * @param targetFile - * @return boolean - */ - private boolean belongsToSamePackage(Class thatClass, File targetFile) - { - boolean result = true; - - File lastParentFile = targetFile.getParentFile(); - String[] packageSpecifierArray = thatClass.getPackage().getName().split("\\."); - - for (int i = packageSpecifierArray.length - 1; i >= 0; i--) - { - String packageName = packageSpecifierArray[i]; - if (packageName.equals(lastParentFile.getName())) - { - lastParentFile = lastParentFile.getParentFile(); - } - else - { - result = false; - break; - } - } - - return result; - } -} +package ecologylab.translators.parser; + +import java.io.File; +import java.io.IOException; + +import ecologylab.serialization.ElementState; + +/** + * Class file to search for java source files. Using the Class type objects this class searches for + * source files inside a root directory recursively. This class is being used by the JavaDocParser + * to fetch java doc comments from source files. + * + * @author nabeel + */ +public class FileTraversal +{ + /** + * Object which persists during recursive file search. + */ + private File searchedFile = null; + + /** + * inputClass which is set when searching for the file. + */ + private Class inputClass; + + /** + * Default constructor. does nothing + */ + public FileTraversal() + { + + } + + /** + * Searches for a given inside a root directory. + * + * @param thatClass + * @param rootLocation + * @return File null if the search did not yield any result. + * @throws IOException + */ + public File searchForFile(Class thatClass, File rootLocation) + throws IOException + { + this.searchedFile = null; + this.inputClass = thatClass; + this.traverse(rootLocation); + + return searchedFile; + } + + /** + * Returns the search file. Use + * File searchForFile(Class thatClass, File rootLocation) + * before using this method. If this value is null than the file was not found. + * + * @return File + */ + public File getSearchedFile() + { + return searchedFile; + } + + /** + * Recursive method to traverse through each file in the root directory. + * + * @param file + * @throws IOException + */ + private final void traverse(final File file) throws IOException + { + if (file.isDirectory()) + { + onDirectory(file); + final File[] childs = file.listFiles(); + for (File child : childs) + { + traverse(child); + } + return; + } + onFile(file); + } + + /** + * This method is invoked if the search passes through a directory. + * + * @param directory + */ + private void onDirectory(final File directory) + { + } + + /** + * This method is invoked if the search passes through a file. + * + * @param targetFile + */ + private void onFile(final File targetFile) + { + if (targetFile.getName().equals(inputClass.getSimpleName() + ".java")) + if (belongsToSamePackage(inputClass, targetFile)) + searchedFile = targetFile; + } + + /** + * Utility method to check if the found source file also belongs to the same package as input + * class. + * + * @param thatClass + * @param targetFile + * @return boolean + */ + private boolean belongsToSamePackage(Class thatClass, File targetFile) + { + boolean result = true; + + File lastParentFile = targetFile.getParentFile(); + String[] packageSpecifierArray = thatClass.getPackage().getName().split("\\."); + + for (int i = packageSpecifierArray.length - 1; i >= 0; i--) + { + String packageName = packageSpecifierArray[i]; + if (packageName.equals(lastParentFile.getName())) + { + lastParentFile = lastParentFile.getParentFile(); + } + else + { + result = false; + break; + } + } + + return result; + } +} diff --git a/simplTranslators/src/ecologylab/translators/parser/JavaDocParser.java b/simplTranslators/src/ecologylab/translators/parser/JavaDocParser.java index 4a3eaee8..e219e6ee 100644 --- a/simplTranslators/src/ecologylab/translators/parser/JavaDocParser.java +++ b/simplTranslators/src/ecologylab/translators/parser/JavaDocParser.java @@ -1,379 +1,379 @@ -package ecologylab.translators.parser; - -import japa.parser.JavaParser; -import japa.parser.ParseException; -import japa.parser.ast.CompilationUnit; -import japa.parser.ast.body.BodyDeclaration; -import japa.parser.ast.body.ClassOrInterfaceDeclaration; -import japa.parser.ast.body.FieldDeclaration; -import japa.parser.ast.body.VariableDeclarator; -import japa.parser.ast.visitor.VoidVisitorAdapter; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.IJavaParser; -import ecologylab.serialization.SimplTypesScope; - -/** - * This class is used to parse java source file and mantain optimized datastructure to hold comments - * on class and fields. - * - * @author nabeel - */ -public class JavaDocParser implements IJavaParser -{ - /** - * Hashmap maps class names to hashmap of fields to java docs on fields - */ - protected static HashMap> javaDocFieldComments = new HashMap>(); - - /** - * Hashmap maps the comments on class to their class names. - */ - protected static HashMap javaDocClassComments = new HashMap(); - - /** - * Simple visitor implementation for visiting Field Visitor nodes. - */ - @SuppressWarnings("unchecked") - private static class FieldVisitor extends VoidVisitorAdapter - { - @Override - public void visit(ClassOrInterfaceDeclaration n, Object arg) - { - if (n != null) - { - String currentClass = n.getName(); - javaDocFieldComments.put(currentClass, new HashMap()); - - if (n.getJavaDoc() != null) - { - javaDocClassComments.put(currentClass, escape(n.getJavaDoc().toString(), 4)); - } - - if (n.getMembers() != null) - { - for (BodyDeclaration member : n.getMembers()) - { - member.accept(this, currentClass); - } - } - } - } - - @Override - public void visit(FieldDeclaration n, Object arg) - { - if (n != null && n.getJavaDoc() != null && arg instanceof String) - { - String currentClass = (String) arg; - HashMap fieldComments = javaDocFieldComments.get(currentClass); - - if (fieldComments != null) - { - for (VariableDeclarator v : n.getVariables()) - { - fieldComments.put(v.toString(), escape(n.getJavaDoc().toString(), 5)); - } - } - } - } - } - - public static String[] getClassJavaDocsArray(Class inputClass) - { - String javaDocs = getClassJavaDocs(inputClass); - if (javaDocs != null) - { - return escapeToArray(javaDocs); - } - else - return null; - } - - /** - * returns the java doc comment for the given class descriptor - * @param inputClass - * @return - */ - public static String[] getClassJavaDocsArray(ClassDescriptor inputClass) - { - String javaDocs = getClassJavaDocs(inputClass.getDescribedClassSimpleName());; - if (javaDocs != null) - { - return escapeToArray(javaDocs); - } - else - return null; - } - - public static String[] getFieldJavaDocsArray(Field field) - { - String javaDocs = getFieldJavaDocs(field); - if (javaDocs != null) - { - return escapeToArray(javaDocs); - } - else - return null; - } - - /** - * returns the java doc comment of the given field descriptor - * - * @param field - * @return - */ - public static String[] getFieldJavaDocsArray(FieldDescriptor field) - { - ClassDescriptor thatClass = field.getDeclaringClassDescriptor(); - String javaDocs = getFieldJavaDocs(thatClass.getDescribedClassSimpleName(), field.getName()); - - if (javaDocs != null) - { - return escapeToArray(javaDocs); - } - else - return null; - } - - /** - * Gets the class level javadocs on the input class file. This method is used in conjunction with - * the static void parse(File file) throws ParseException, IOException method. - * - * @param inputClass - * @return String - */ - public static String getClassJavaDocs(Class inputClass) - { - return getClassJavaDocs(inputClass.getSimpleName()); - } - - /** - * Gets the class level javadocs on the input class. This method is used in conjunction with the - * static void parse(File file) throws ParseException, IOException method. - * - * @param className - * @return - */ - public static String getClassJavaDocs(String className) - { - return javaDocClassComments.get(className); - } - - /** - * Gets the field level javadocs comments on the input file. This method is used in conjunction - * with the static void parse(File file) throws ParseException, IOException method. - * - * @param thatField - * @return - */ - public static String getFieldJavaDocs(Field thatField) - { - if(thatField != null) - { - Class thatClass = thatField.getDeclaringClass(); - return getFieldJavaDocs(thatClass.getSimpleName(), thatField.getName()); - } - return ""; - } - - /** - * @param className - * @param fieldName - * @return - */ - public static String getFieldJavaDocs(String className, String fieldName) - { - String javaDocs = null; - HashMap fieldCommentsMap = javaDocFieldComments.get(className); - if (fieldCommentsMap != null) - { - javaDocs = fieldCommentsMap.get(fieldName); - } - return javaDocs; - } - - /** - * Parses the input file and fills up the internal optimized data structures with formatted - * comments in the given java source file. - * - * @param file - * @throws ParseException - * @throws IOException - * @return True if the parse was successful - */ - @SuppressWarnings("unchecked") - public static boolean parse(File file) throws ParseException, IOException - { - CompilationUnit cu; - cu = JavaParser.parse(file); - new FieldVisitor().visit(cu, null); - - return true; - } - - public static void parseSourceFileIfExists(SimplTypesScope translationScope, - File workSpaceLocation) throws IOException - { - try - { - ArrayList> classes = translationScope.getAllClasses(); - int length = classes.size(); - - for (int i = 0; i < length; i++) - { - parseSourceFileIfExists(classes.get(i), workSpaceLocation); - } - } - catch (ParseException e) - { - e.printStackTrace(); - } - } - - private static void parseSourceFileIfExists(Class inputClass, - File workSpaceLocation) throws ParseException, IOException - { - if (workSpaceLocation != null) - { - File sourceFile = findFile(inputClass, workSpaceLocation); - if (sourceFile != null) - { - parse(sourceFile); - } - } - } - - private static File findFile(Class inputClass, File workSpaceLocation) - throws IOException - { - FileTraversal fileTraversal = new FileTraversal(); - return fileTraversal.searchForFile(inputClass, workSpaceLocation); - } - - /** - * Escapes invisible characters from the comments and does tab formatting on the comments. - * - * @param javaDocs - * @param numOfTabs - * @return String : formatted String comment - */ - private static String escape(String javaDocs, int numOfTabs) - { - String tabString = makeTabString(numOfTabs); - - String strippedComments = javaDocs.replace("*", "").replace("/", "").trim(); - String[] commentsArray = strippedComments.split("\n"); - - StringBuilder finalComment = new StringBuilder(); - - for (String part : commentsArray) - { - part = part.trim(); - if (!part.isEmpty()) - finalComment.append(part).append("\n" + tabString); - } - - return finalComment.toString().trim(); - } - - private static String[] escapeToArray(String javaDocs) - { - String strippedComments = javaDocs.replace("*", "").replace("/", "").trim(); - String[] commentsArray = strippedComments.split("\n"); - - for (int i = 0; i < commentsArray.length; i++) - { - commentsArray[i] = commentsArray[i].trim(); - } - - return commentsArray; - } - - /** - * Makes a string of tabs used for formatting - * - * @param numOfTabs - * @return String - */ - private static String makeTabString(int numOfTabs) - { - StringBuilder tabString = new StringBuilder(); - for (int i = 0; i < numOfTabs; i++) - { - tabString.append('\t'); - } - return tabString.toString(); - } - - @Override - public String getJavaDocComment(Class thatClass){ - try - { - File sourceFile = new File(getJavaFilePath(thatClass)); - if (sourceFile != null) - { - parse(sourceFile); - javaDocFieldComments.isEmpty(); - return javaDocClassComments.get(thatClass.getSimpleName()); - } - }catch(Exception ex) - { - // exception handling code - } - return ""; - } - - @Override - public String getJavaDocComment(Field field) { - // TODO Auto-generated method stub - try - { - HashMap fieldComments = javaDocFieldComments.get(field.getDeclaringClass().getSimpleName()); - if(fieldComments == null) - { - getJavaDocComment(field.getDeclaringClass()); - fieldComments = javaDocFieldComments.get(field.getDeclaringClass().getSimpleName()); - } - if(fieldComments != null) - { - return fieldComments.get(field.getName()); - } - }catch(Exception ex) - { - // exception handling code - } - return ""; - } - - /** - * return the path of the java source file - * @param javaClass - * @return - */ - private String getJavaFilePath(Class javaClass) - { - URL location; - String classLocation = javaClass.getName().replace('.', '/') + ".java"; - final ClassLoader loader = javaClass.getClassLoader(); - if (loader == null) - { - location = null; - System.out.println("Cannot load the class"); - } else - { - location = loader.getResource(classLocation); - System.out.println("Class "+location); - } - return (location==null)?"":location.getPath(); - } -} +package ecologylab.translators.parser; + +import japa.parser.JavaParser; +import japa.parser.ParseException; +import japa.parser.ast.CompilationUnit; +import japa.parser.ast.body.BodyDeclaration; +import japa.parser.ast.body.ClassOrInterfaceDeclaration; +import japa.parser.ast.body.FieldDeclaration; +import japa.parser.ast.body.VariableDeclarator; +import japa.parser.ast.visitor.VoidVisitorAdapter; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.IJavaParser; +import ecologylab.serialization.SimplTypesScope; + +/** + * This class is used to parse java source file and mantain optimized datastructure to hold comments + * on class and fields. + * + * @author nabeel + */ +public class JavaDocParser implements IJavaParser +{ + /** + * Hashmap maps class names to hashmap of fields to java docs on fields + */ + protected static HashMap> javaDocFieldComments = new HashMap>(); + + /** + * Hashmap maps the comments on class to their class names. + */ + protected static HashMap javaDocClassComments = new HashMap(); + + /** + * Simple visitor implementation for visiting Field Visitor nodes. + */ + @SuppressWarnings("unchecked") + private static class FieldVisitor extends VoidVisitorAdapter + { + @Override + public void visit(ClassOrInterfaceDeclaration n, Object arg) + { + if (n != null) + { + String currentClass = n.getName(); + javaDocFieldComments.put(currentClass, new HashMap()); + + if (n.getJavaDoc() != null) + { + javaDocClassComments.put(currentClass, escape(n.getJavaDoc().toString(), 4)); + } + + if (n.getMembers() != null) + { + for (BodyDeclaration member : n.getMembers()) + { + member.accept(this, currentClass); + } + } + } + } + + @Override + public void visit(FieldDeclaration n, Object arg) + { + if (n != null && n.getJavaDoc() != null && arg instanceof String) + { + String currentClass = (String) arg; + HashMap fieldComments = javaDocFieldComments.get(currentClass); + + if (fieldComments != null) + { + for (VariableDeclarator v : n.getVariables()) + { + fieldComments.put(v.toString(), escape(n.getJavaDoc().toString(), 5)); + } + } + } + } + } + + public static String[] getClassJavaDocsArray(Class inputClass) + { + String javaDocs = getClassJavaDocs(inputClass); + if (javaDocs != null) + { + return escapeToArray(javaDocs); + } + else + return null; + } + + /** + * returns the java doc comment for the given class descriptor + * @param inputClass + * @return + */ + public static String[] getClassJavaDocsArray(ClassDescriptor inputClass) + { + String javaDocs = getClassJavaDocs(inputClass.getDescribedClassSimpleName());; + if (javaDocs != null) + { + return escapeToArray(javaDocs); + } + else + return null; + } + + public static String[] getFieldJavaDocsArray(Field field) + { + String javaDocs = getFieldJavaDocs(field); + if (javaDocs != null) + { + return escapeToArray(javaDocs); + } + else + return null; + } + + /** + * returns the java doc comment of the given field descriptor + * + * @param field + * @return + */ + public static String[] getFieldJavaDocsArray(FieldDescriptor field) + { + ClassDescriptor thatClass = field.getDeclaringClassDescriptor(); + String javaDocs = getFieldJavaDocs(thatClass.getDescribedClassSimpleName(), field.getName()); + + if (javaDocs != null) + { + return escapeToArray(javaDocs); + } + else + return null; + } + + /** + * Gets the class level javadocs on the input class file. This method is used in conjunction with + * the static void parse(File file) throws ParseException, IOException method. + * + * @param inputClass + * @return String + */ + public static String getClassJavaDocs(Class inputClass) + { + return getClassJavaDocs(inputClass.getSimpleName()); + } + + /** + * Gets the class level javadocs on the input class. This method is used in conjunction with the + * static void parse(File file) throws ParseException, IOException method. + * + * @param className + * @return + */ + public static String getClassJavaDocs(String className) + { + return javaDocClassComments.get(className); + } + + /** + * Gets the field level javadocs comments on the input file. This method is used in conjunction + * with the static void parse(File file) throws ParseException, IOException method. + * + * @param thatField + * @return + */ + public static String getFieldJavaDocs(Field thatField) + { + if(thatField != null) + { + Class thatClass = thatField.getDeclaringClass(); + return getFieldJavaDocs(thatClass.getSimpleName(), thatField.getName()); + } + return ""; + } + + /** + * @param className + * @param fieldName + * @return + */ + public static String getFieldJavaDocs(String className, String fieldName) + { + String javaDocs = null; + HashMap fieldCommentsMap = javaDocFieldComments.get(className); + if (fieldCommentsMap != null) + { + javaDocs = fieldCommentsMap.get(fieldName); + } + return javaDocs; + } + + /** + * Parses the input file and fills up the internal optimized data structures with formatted + * comments in the given java source file. + * + * @param file + * @throws ParseException + * @throws IOException + * @return True if the parse was successful + */ + @SuppressWarnings("unchecked") + public static boolean parse(File file) throws ParseException, IOException + { + CompilationUnit cu; + cu = JavaParser.parse(file); + new FieldVisitor().visit(cu, null); + + return true; + } + + public static void parseSourceFileIfExists(SimplTypesScope translationScope, + File workSpaceLocation) throws IOException + { + try + { + ArrayList> classes = translationScope.getAllClasses(); + int length = classes.size(); + + for (int i = 0; i < length; i++) + { + parseSourceFileIfExists(classes.get(i), workSpaceLocation); + } + } + catch (ParseException e) + { + e.printStackTrace(); + } + } + + private static void parseSourceFileIfExists(Class inputClass, + File workSpaceLocation) throws ParseException, IOException + { + if (workSpaceLocation != null) + { + File sourceFile = findFile(inputClass, workSpaceLocation); + if (sourceFile != null) + { + parse(sourceFile); + } + } + } + + private static File findFile(Class inputClass, File workSpaceLocation) + throws IOException + { + FileTraversal fileTraversal = new FileTraversal(); + return fileTraversal.searchForFile(inputClass, workSpaceLocation); + } + + /** + * Escapes invisible characters from the comments and does tab formatting on the comments. + * + * @param javaDocs + * @param numOfTabs + * @return String : formatted String comment + */ + private static String escape(String javaDocs, int numOfTabs) + { + String tabString = makeTabString(numOfTabs); + + String strippedComments = javaDocs.replace("*", "").replace("/", "").trim(); + String[] commentsArray = strippedComments.split("\n"); + + StringBuilder finalComment = new StringBuilder(); + + for (String part : commentsArray) + { + part = part.trim(); + if (!part.isEmpty()) + finalComment.append(part).append("\n" + tabString); + } + + return finalComment.toString().trim(); + } + + private static String[] escapeToArray(String javaDocs) + { + String strippedComments = javaDocs.replace("*", "").replace("/", "").trim(); + String[] commentsArray = strippedComments.split("\n"); + + for (int i = 0; i < commentsArray.length; i++) + { + commentsArray[i] = commentsArray[i].trim(); + } + + return commentsArray; + } + + /** + * Makes a string of tabs used for formatting + * + * @param numOfTabs + * @return String + */ + private static String makeTabString(int numOfTabs) + { + StringBuilder tabString = new StringBuilder(); + for (int i = 0; i < numOfTabs; i++) + { + tabString.append('\t'); + } + return tabString.toString(); + } + + @Override + public String getJavaDocComment(Class thatClass){ + try + { + File sourceFile = new File(getJavaFilePath(thatClass)); + if (sourceFile != null) + { + parse(sourceFile); + javaDocFieldComments.isEmpty(); + return javaDocClassComments.get(thatClass.getSimpleName()); + } + }catch(Exception ex) + { + // exception handling code + } + return ""; + } + + @Override + public String getJavaDocComment(Field field) { + // TODO Auto-generated method stub + try + { + HashMap fieldComments = javaDocFieldComments.get(field.getDeclaringClass().getSimpleName()); + if(fieldComments == null) + { + getJavaDocComment(field.getDeclaringClass()); + fieldComments = javaDocFieldComments.get(field.getDeclaringClass().getSimpleName()); + } + if(fieldComments != null) + { + return fieldComments.get(field.getName()); + } + }catch(Exception ex) + { + // exception handling code + } + return ""; + } + + /** + * return the path of the java source file + * @param javaClass + * @return + */ + private String getJavaFilePath(Class javaClass) + { + URL location; + String classLocation = javaClass.getName().replace('.', '/') + ".java"; + final ClassLoader loader = javaClass.getClassLoader(); + if (loader == null) + { + location = null; + System.out.println("Cannot load the class"); + } else + { + location = loader.getResource(classLocation); + System.out.println("Class "+location); + } + return (location==null)?"":location.getPath(); + } +} diff --git a/simplTranslators/src/ecologylab/translators/parser/package.html b/simplTranslators/src/ecologylab/translators/parser/package.html index a01afabd..4f102a7c 100644 --- a/simplTranslators/src/ecologylab/translators/parser/package.html +++ b/simplTranslators/src/ecologylab/translators/parser/package.html @@ -1,3 +1,3 @@ - -Contains files for searching for java source files and parsing java doc comments from the source files + +Contains files for searching for java source files and parsing java doc comments from the source files \ No newline at end of file diff --git a/simplTranslators/src/ecologylab/translators/sql/DBSerializer.java b/simplTranslators/src/ecologylab/translators/sql/DBSerializer.java index 610620ff..4ae963a9 100644 --- a/simplTranslators/src/ecologylab/translators/sql/DBSerializer.java +++ b/simplTranslators/src/ecologylab/translators/sql/DBSerializer.java @@ -1,393 +1,393 @@ -package ecologylab.translators.sql; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; - -/** - * This class uses PostgreSQL's object oriented features to store Java Objects. - * - */ -public class DBSerializer -{ - // This is the connection that the instance refers to - protected/* org.postgresql. */DBUtil conn; - - // This is the table name - protected String tableName; - - // This is the class name - protected String className; - - // This is the Class for this serialzed object - protected Class ourClass; - - /** - * This creates an instance that can be used to serialize or deserialize a Java object from a - * PostgreSQL table. - */ - public DBSerializer(/* org.postgresql. */Connection c, String type) throws SQLException - { - try - { - // conn = c; - tableName = type.toLowerCase(); - className = toClassName(type); - ourClass = Class.forName(className); - } - catch (ClassNotFoundException cnfe) - { - // throw new PSQLException("postgresql.serial.noclass",type); - } - - // Second check, the type must be a table - boolean status = false; - ResultSet rs = conn - .ExecSQL("select typname from pg_type,pg_class where typname=relname and typname='" + type - + "'"); - if (rs != null) - { - if (rs.next()) - status = true; - rs.close(); - } - // This should never occur, as org.postgresql has it's own internal checks - /* - * if(!status) throw new PSQLException("postgresql.serial.table",type); - */ - // Finally cache the fields within the table - } - - /** - * This fetches an object from a table, given it's OID - * - * @param oid - * The oid of the object - * @return Object relating to oid - * @exception SQLException - * on error - */ - public Object fetch(int oid) throws SQLException - { - try - { - Object obj = ourClass.newInstance(); - - // NB: we use java.lang.reflect here to prevent confusion with - // the org.postgresql.Field - java.lang.reflect.Field f[] = ourClass.getDeclaredFields(); - boolean hasOID = false; - int oidFIELD = -1; - StringBuffer sb = new StringBuffer("select"); - char sep = ' '; - for (int i = 0; i < f.length; i++) - { - String n = f[i].getName(); - if (n.equals("oid")) - { - hasOID = true; - oidFIELD = i; - } - sb.append(sep); - sb.append(n); - sep = ','; - } - sb.append(" from "); - sb.append(tableName); - sb.append(" where oid="); - sb.append(oid); - - DriverManager.println("store: " + sb.toString()); - ResultSet rs = conn.ExecSQL(sb.toString()); - if (rs != null) - { - if (rs.next()) - { - for (int i = 0; i < f.length; i++) - { - f[i].set(obj, rs.getObject(i + 1)); - } - } - rs.close(); - } - else - // throw new PSQLException("postgresql.unexpected"); - return obj; - } - catch (IllegalAccessException iae) - { - throw new SQLException(iae.toString()); - } - catch (InstantiationException ie) - { - throw new SQLException(ie.toString()); - } - /* TODO remove */ - return oid; - } - - /** - * This stores an object into a table, returning it's OID. - *

- * - * If the object has an int called OID, and it is > 0, then that value is used for the OID, and - * the table will be updated. If the value of OID is 0, then a new row will be created, and the - * value of OID will be set in the object. This enables an object's value in the database to be - * updateable. - * - * If the object has no int called OID, then the object is stored. However if the object is later - * retrieved, amended and stored again, it's new state will be appended to the table, and will not - * overwrite the old entries. - * - * @param o - * Object to store (must implement Serializable) - * @return oid of stored object - * @exception SQLException - * on error - */ - public int store(Object o) throws SQLException - { - try - { - // NB: we use java.lang.reflect here to prevent confusion with - // the org.postgresql.Field - java.lang.reflect.Field f[] = ourClass.getDeclaredFields(); - boolean hasOID = false; - int oidFIELD = -1; - boolean update = false; - - // Find out if we have an oid value - for (int i = 0; i < f.length; i++) - { - String n = f[i].getName(); - if (n.equals("oid")) - { - hasOID = true; - oidFIELD = i; - - // We are an update if oid != 0 - update = f[i].getInt(o) > 0; - } - } - - StringBuffer sb = new StringBuffer(update ? "update " + tableName + " set" : "insert into " - + tableName + " values "); - char sep = update ? ' ' : '('; - for (int i = 0; i < f.length; i++) - { - String n = f[i].getName(); - sb.append(sep); - sb.append(n); - sep = ','; - if (update) - { - sb.append('='); - if (f[i].getType().getName().equals("java.lang.String")) - { - sb.append('\''); - sb.append(f[i].get(o).toString()); - sb.append('\''); - } - else - sb.append(f[i].get(o).toString()); - } - } - - if (!update) - { - sb.append(") values "); - sep = '('; - for (int i = 0; i < f.length; i++) - { - String n = f[i].getName(); - if (f[i].getType().getName().equals("java.lang.String")) - { - sb.append('\''); - sb.append(f[i].get(o).toString()); - sb.append('\''); - } - else - sb.append(f[i].get(o).toString()); - } - sb.append(')'); - } - - DriverManager.println("store: " + sb.toString()); - ResultSet rs = conn.ExecSQL(sb.toString()); - if (rs != null) - { - rs.close(); - } - - // fetch the OID for returning - int oid = 0; - if (hasOID) - { - // set the oid in the object - f[oidFIELD].setInt(o, oid); - } - return oid; - - } - catch (IllegalAccessException iae) - { - throw new SQLException(iae.toString()); - } - } - - /** - * This method is not used by the driver, but it creates a table, given a Serializable Java - * Object. It should be used before serializing any objects. - * - * @param c - * Connection to database - * @param o - * Object to base table on - * @exception SQLException - * on error - */ - public static void create(/* org.postgresql. */Connection con, Object o) throws SQLException - { - create(con, o.getClass()); - } - - /** - * This method is not used by the driver, but it creates a table, given a Serializable Java - * Object. It should be used before serializing any objects. - * - * @param c - * Connection to database - * @param o - * Class to base table on - * @throws Exception - */ - public static void create(/* org.postgresql. *//* Connection */DBUtil con, Class c) - throws Exception - { - if (c.isInterface()) - // throw new PSQLException("postgresql.serial.interface"); - throw new Exception("postgresql.serial.interface"); - - // See if the table exists - String tableName = toPostgreSQL(c.getName()); - - ResultSet rs = con.ExecSQL("select relname from pg_class where relname = '" + tableName + "'"); - if (!rs.next()) - { - DriverManager.println("found " + rs.getString(1)); - // No entries returned, so the table doesn't exist - - StringBuffer sb = new StringBuffer("create table "); - sb.append(tableName); - char sep = '('; - - java.lang.reflect.Field[] fields = c.getDeclaredFields(); - for (int i = 0; i < fields.length; i++) - { - Class type = fields[i].getType(); - - // oid is a special field - if (!fields[i].getName().equals("oid")) - { - sb.append(sep); - sb.append(fields[i].getName()); - sb.append(' '); - sep = ','; - - if (type.isArray()) - { - // array handling - } - else - { - // convert the java type to org.postgresql, recursing if a class - // is found - String n = fields[i].getType().getName(); - int j = 0; - for (; j < tp.length && !tp[j][0].equals(n); j++) - ; - if (j < tp.length) - sb.append(tp[j][1]); - else - { - create(con, fields[i].getType()); - sb.append(toPostgreSQL(n)); - } - } - } - } - sb.append(")"); - - // Now create the table - DriverManager.println("Serialize.create:" + sb); - con.ExecSQL(sb.toString()); - rs.close(); - } - else - { - DriverManager.println("Serialize.create: table " + tableName + " exists, skipping"); - } - } - - // This is used to translate between Java primitives and PostgreSQL types. - private static final String tp[][] = - { - { "boolean", "int1" }, - { "double", "float8" }, - { "float", "float4" }, - { "int", "int4" }, - { "long", "int4" }, - { "short", "int2" }, - { "java.lang.String", "text" }, - { "java.lang.Integer", "int4" }, - { "java.lang.Float", "float4" }, - { "java.lang.Double", "float8" }, - { "java.lang.Short", "int2" } }; - - /** - * This converts a Java Class name to a org.postgresql table, by replacing . with _ - *

- * - * Because of this, a Class name may not have _ in the name. - *

- * Another limitation, is that the entire class name (including packages) cannot be longer than 32 - * characters (a limit forced by PostgreSQL). - * - * @param name - * Class name - * @return PostgreSQL table name - * @throws Exception - */ - public static String toPostgreSQL(String name) throws Exception - { - name = name.toLowerCase(); - - if (name.indexOf("_") > -1) - // throw new PSQLException("postgresql.serial.underscore"); - throw new Exception("postgresql.serial.underscore"); - - if (name.length() > 32) - // throw new PSQLException("postgresql.serial.namelength",name,new Integer(name.length())); - throw new Exception("postgresql.serial.namelength"); - - return name.replace('.', '_'); - } - - /** - * This converts a org.postgresql table to a Java Class name, by replacing _ with . - *

- * - * @param name - * PostgreSQL table name - * @return Class name - * @exception SQLException - * on error - */ - public static String toClassName(String name) throws SQLException - { - name = name.toLowerCase(); - return name.replace('_', '.'); - } - -} +package ecologylab.translators.sql; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * This class uses PostgreSQL's object oriented features to store Java Objects. + * + */ +public class DBSerializer +{ + // This is the connection that the instance refers to + protected/* org.postgresql. */DBUtil conn; + + // This is the table name + protected String tableName; + + // This is the class name + protected String className; + + // This is the Class for this serialzed object + protected Class ourClass; + + /** + * This creates an instance that can be used to serialize or deserialize a Java object from a + * PostgreSQL table. + */ + public DBSerializer(/* org.postgresql. */Connection c, String type) throws SQLException + { + try + { + // conn = c; + tableName = type.toLowerCase(); + className = toClassName(type); + ourClass = Class.forName(className); + } + catch (ClassNotFoundException cnfe) + { + // throw new PSQLException("postgresql.serial.noclass",type); + } + + // Second check, the type must be a table + boolean status = false; + ResultSet rs = conn + .ExecSQL("select typname from pg_type,pg_class where typname=relname and typname='" + type + + "'"); + if (rs != null) + { + if (rs.next()) + status = true; + rs.close(); + } + // This should never occur, as org.postgresql has it's own internal checks + /* + * if(!status) throw new PSQLException("postgresql.serial.table",type); + */ + // Finally cache the fields within the table + } + + /** + * This fetches an object from a table, given it's OID + * + * @param oid + * The oid of the object + * @return Object relating to oid + * @exception SQLException + * on error + */ + public Object fetch(int oid) throws SQLException + { + try + { + Object obj = ourClass.newInstance(); + + // NB: we use java.lang.reflect here to prevent confusion with + // the org.postgresql.Field + java.lang.reflect.Field f[] = ourClass.getDeclaredFields(); + boolean hasOID = false; + int oidFIELD = -1; + StringBuffer sb = new StringBuffer("select"); + char sep = ' '; + for (int i = 0; i < f.length; i++) + { + String n = f[i].getName(); + if (n.equals("oid")) + { + hasOID = true; + oidFIELD = i; + } + sb.append(sep); + sb.append(n); + sep = ','; + } + sb.append(" from "); + sb.append(tableName); + sb.append(" where oid="); + sb.append(oid); + + DriverManager.println("store: " + sb.toString()); + ResultSet rs = conn.ExecSQL(sb.toString()); + if (rs != null) + { + if (rs.next()) + { + for (int i = 0; i < f.length; i++) + { + f[i].set(obj, rs.getObject(i + 1)); + } + } + rs.close(); + } + else + // throw new PSQLException("postgresql.unexpected"); + return obj; + } + catch (IllegalAccessException iae) + { + throw new SQLException(iae.toString()); + } + catch (InstantiationException ie) + { + throw new SQLException(ie.toString()); + } + /* TODO remove */ + return oid; + } + + /** + * This stores an object into a table, returning it's OID. + *

+ * + * If the object has an int called OID, and it is > 0, then that value is used for the OID, and + * the table will be updated. If the value of OID is 0, then a new row will be created, and the + * value of OID will be set in the object. This enables an object's value in the database to be + * updateable. + * + * If the object has no int called OID, then the object is stored. However if the object is later + * retrieved, amended and stored again, it's new state will be appended to the table, and will not + * overwrite the old entries. + * + * @param o + * Object to store (must implement Serializable) + * @return oid of stored object + * @exception SQLException + * on error + */ + public int store(Object o) throws SQLException + { + try + { + // NB: we use java.lang.reflect here to prevent confusion with + // the org.postgresql.Field + java.lang.reflect.Field f[] = ourClass.getDeclaredFields(); + boolean hasOID = false; + int oidFIELD = -1; + boolean update = false; + + // Find out if we have an oid value + for (int i = 0; i < f.length; i++) + { + String n = f[i].getName(); + if (n.equals("oid")) + { + hasOID = true; + oidFIELD = i; + + // We are an update if oid != 0 + update = f[i].getInt(o) > 0; + } + } + + StringBuffer sb = new StringBuffer(update ? "update " + tableName + " set" : "insert into " + + tableName + " values "); + char sep = update ? ' ' : '('; + for (int i = 0; i < f.length; i++) + { + String n = f[i].getName(); + sb.append(sep); + sb.append(n); + sep = ','; + if (update) + { + sb.append('='); + if (f[i].getType().getName().equals("java.lang.String")) + { + sb.append('\''); + sb.append(f[i].get(o).toString()); + sb.append('\''); + } + else + sb.append(f[i].get(o).toString()); + } + } + + if (!update) + { + sb.append(") values "); + sep = '('; + for (int i = 0; i < f.length; i++) + { + String n = f[i].getName(); + if (f[i].getType().getName().equals("java.lang.String")) + { + sb.append('\''); + sb.append(f[i].get(o).toString()); + sb.append('\''); + } + else + sb.append(f[i].get(o).toString()); + } + sb.append(')'); + } + + DriverManager.println("store: " + sb.toString()); + ResultSet rs = conn.ExecSQL(sb.toString()); + if (rs != null) + { + rs.close(); + } + + // fetch the OID for returning + int oid = 0; + if (hasOID) + { + // set the oid in the object + f[oidFIELD].setInt(o, oid); + } + return oid; + + } + catch (IllegalAccessException iae) + { + throw new SQLException(iae.toString()); + } + } + + /** + * This method is not used by the driver, but it creates a table, given a Serializable Java + * Object. It should be used before serializing any objects. + * + * @param c + * Connection to database + * @param o + * Object to base table on + * @exception SQLException + * on error + */ + public static void create(/* org.postgresql. */Connection con, Object o) throws SQLException + { + create(con, o.getClass()); + } + + /** + * This method is not used by the driver, but it creates a table, given a Serializable Java + * Object. It should be used before serializing any objects. + * + * @param c + * Connection to database + * @param o + * Class to base table on + * @throws Exception + */ + public static void create(/* org.postgresql. *//* Connection */DBUtil con, Class c) + throws Exception + { + if (c.isInterface()) + // throw new PSQLException("postgresql.serial.interface"); + throw new Exception("postgresql.serial.interface"); + + // See if the table exists + String tableName = toPostgreSQL(c.getName()); + + ResultSet rs = con.ExecSQL("select relname from pg_class where relname = '" + tableName + "'"); + if (!rs.next()) + { + DriverManager.println("found " + rs.getString(1)); + // No entries returned, so the table doesn't exist + + StringBuffer sb = new StringBuffer("create table "); + sb.append(tableName); + char sep = '('; + + java.lang.reflect.Field[] fields = c.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) + { + Class type = fields[i].getType(); + + // oid is a special field + if (!fields[i].getName().equals("oid")) + { + sb.append(sep); + sb.append(fields[i].getName()); + sb.append(' '); + sep = ','; + + if (type.isArray()) + { + // array handling + } + else + { + // convert the java type to org.postgresql, recursing if a class + // is found + String n = fields[i].getType().getName(); + int j = 0; + for (; j < tp.length && !tp[j][0].equals(n); j++) + ; + if (j < tp.length) + sb.append(tp[j][1]); + else + { + create(con, fields[i].getType()); + sb.append(toPostgreSQL(n)); + } + } + } + } + sb.append(")"); + + // Now create the table + DriverManager.println("Serialize.create:" + sb); + con.ExecSQL(sb.toString()); + rs.close(); + } + else + { + DriverManager.println("Serialize.create: table " + tableName + " exists, skipping"); + } + } + + // This is used to translate between Java primitives and PostgreSQL types. + private static final String tp[][] = + { + { "boolean", "int1" }, + { "double", "float8" }, + { "float", "float4" }, + { "int", "int4" }, + { "long", "int4" }, + { "short", "int2" }, + { "java.lang.String", "text" }, + { "java.lang.Integer", "int4" }, + { "java.lang.Float", "float4" }, + { "java.lang.Double", "float8" }, + { "java.lang.Short", "int2" } }; + + /** + * This converts a Java Class name to a org.postgresql table, by replacing . with _ + *

+ * + * Because of this, a Class name may not have _ in the name. + *

+ * Another limitation, is that the entire class name (including packages) cannot be longer than 32 + * characters (a limit forced by PostgreSQL). + * + * @param name + * Class name + * @return PostgreSQL table name + * @throws Exception + */ + public static String toPostgreSQL(String name) throws Exception + { + name = name.toLowerCase(); + + if (name.indexOf("_") > -1) + // throw new PSQLException("postgresql.serial.underscore"); + throw new Exception("postgresql.serial.underscore"); + + if (name.length() > 32) + // throw new PSQLException("postgresql.serial.namelength",name,new Integer(name.length())); + throw new Exception("postgresql.serial.namelength"); + + return name.replace('.', '_'); + } + + /** + * This converts a org.postgresql table to a Java Class name, by replacing _ with . + *

+ * + * @param name + * PostgreSQL table name + * @return Class name + * @exception SQLException + * on error + */ + public static String toClassName(String name) throws SQLException + { + name = name.toLowerCase(); + return name.replace('_', '.'); + } + +} diff --git a/simplTranslators/src/ecologylab/translators/sql/output/postgreSQLOutput2.sql b/simplTranslators/src/ecologylab/translators/sql/output/postgreSQLOutput2.sql index 2d7efade..a81105e3 100644 --- a/simplTranslators/src/ecologylab/translators/sql/output/postgreSQLOutput2.sql +++ b/simplTranslators/src/ecologylab/translators/sql/output/postgreSQLOutput2.sql @@ -1,638 +1,638 @@ ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Rss] -CREATE TABLE Rss ( -channel Channel /*simpl_composite */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Search] -CREATE TABLE Search ( -searchResults SearchResult[] /*simpl_collection simpl_nowrap */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.IcdlImage] -CREATE TABLE IcdlImage ( -languages text /*simpl_scalar */ -)INHERITS (Image); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Channel] -CREATE TABLE Channel ( -item Item[] /*simpl_collection simpl_nowrap */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.YahooResultSet] -CREATE TABLE YahooResultSet ( -results Result[] /*simpl_collection simpl_nowrap */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.GooglePatent] -CREATE TABLE GooglePatent ( -claims text , /*simpl_scalar */ -picLinks SearchResult[] , /*simpl_collection */ -citations SearchResult[] , /*simpl_collection */ -abstractField text , /*simpl_scalar */ -referencedBys SearchResult[] , /*simpl_collection */ -inventor text , /*simpl_scalar */ -picLink varchar(64) /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrImage] -CREATE TABLE FlickrImage ( -browsePurl varchar(64) , /*simpl_scalar */ -flickrTags FlickrTag[] /*simpl_collection */ -)INHERITS (Image); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Paragraph] -CREATE TABLE Paragraph ( -anchors Anchor[] , /*simpl_collection */ -paragraphText text /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.DcDocument] -CREATE TABLE DcDocument ( -subject text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Item] -CREATE TABLE Item ( -guid varchar(64) , /*simpl_scalar simpl_hints */ -title text , /*simpl_scalar simpl_hints */ -link varchar(64) /*simpl_scalar simpl_hints */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.WeatherReport] -CREATE TABLE WeatherReport ( -wind text , /*simpl_scalar */ -humidity text , /*simpl_scalar */ -picUrl varchar(64) , /*simpl_scalar */ -weather text , /*simpl_scalar */ -dewPoint text , /*simpl_scalar */ -temperature text , /*simpl_scalar */ -city text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.SearchResult] -CREATE TABLE SearchResult ( -link varchar(64) , /*simpl_scalar */ -snippet text , /*simpl_scalar */ -heading text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.imdb.Genre] -CREATE TABLE Genre ( -name text , /*simpl_scalar */ -genreLink varchar(64) /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrLink] -CREATE TABLE FlickrLink ( -title text , /*simpl_scalar */ -link varchar(64) /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrAuthor] -CREATE TABLE FlickrAuthor ( -flickrLinkSet FlickrLink[] /*simpl_collection */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.ScholarlyArticle] -CREATE TABLE ScholarlyArticle ( -classifications Link[] , /*simpl_collection */ -authors Author[] , /*simpl_collection */ -"references" ScholarlyArticle[] , /*simpl_collection */ -metadataPage varchar(64) , /*simpl_scalar */ -citations ScholarlyArticle[] , /*simpl_collection */ -source Source , /*simpl_composite */ -abstractField text , /*xml_tag simpl_scalar */ -keyTerms Link[] /*simpl_collection */ -)INHERITS (Pdf); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Result] -CREATE TABLE Result ( -summary text , /*xml_tag simpl_scalar simpl_hints */ -title text , /*xml_tag simpl_scalar simpl_hints */ -refererUrl varchar(64) , /*xml_tag simpl_scalar simpl_hints */ -modificationDate int4 , /*xml_tag simpl_scalar simpl_hints */ -mimeType text , /*xml_tag simpl_scalar simpl_hints */ -url varchar(64) /*xml_tag simpl_scalar simpl_hints */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.Media] -CREATE TABLE Media ( -context text /*xml_tag simpl_scalar simpl_hints */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Artwork] -CREATE TABLE Artwork ( -artists Author[] , /*simpl_collection */ -website varchar(64) , /*simpl_scalar */ -abstractField text , /*xml_tag simpl_scalar */ -year text , /*simpl_scalar */ -medium text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.GoogleTrends] -CREATE TABLE GoogleTrends ( -hotSearches HotSearch[] /*simpl_collection simpl_nowrap */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Thumbinner] -CREATE TABLE Thumbinner ( -thumbImgCaption text , /*simpl_scalar */ -thumbImgSrc varchar(64) /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.MmArtwork] -CREATE TABLE MmArtwork ( -artists Author[] , /*simpl_collection */ -website varchar(64) , /*simpl_scalar */ -abstractField text , /*xml_tag simpl_scalar */ -year text , /*simpl_scalar */ -extendedAbstract varchar(64) , /*simpl_scalar */ -artTitle text , /*simpl_scalar */ -medium text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrSearch] -CREATE TABLE FlickrSearch ( -flickrResults FlickrImage[] /*simpl_collection */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrTags] -CREATE TABLE FlickrTags ( -flickrLinkSet FlickrLink[] /*simpl_collection */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Nsdl] -CREATE TABLE Nsdl ( -subject text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.imdb.CastMember] -CREATE TABLE CastMember ( -actor Entity , /*simpl_composite */ -"character" Entity /*simpl_composite */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.Source] -CREATE TABLE Source ( -isbn text , /*simpl_scalar */ -pages text , /*simpl_scalar */ -archive varchar(64) , /*simpl_scalar */ -yearOfPublication int4 /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.imdb.ImdbTitle] -CREATE TABLE ImdbTitle ( -posterImg varchar(64) , /*simpl_scalar */ -releaseDate text , /*simpl_scalar */ -"cast" CastMember[] , /*simpl_collection */ -genres Genre[] , /*simpl_collection */ -yearReleased text , /*simpl_scalar */ -writers PersonDetails[] , /*simpl_collection */ -titlePhotos Image[] , /*simpl_collection */ -rating text , /*simpl_scalar */ -directors PersonDetails[] , /*simpl_collection */ -tagline text , /*simpl_scalar */ -plot text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Anchor] -CREATE TABLE Anchor ( -anchorText text , /*simpl_scalar */ -link varchar(64) /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.metadata.Metadata] -CREATE TABLE Metadata ( -mixins Metadata[] , /*semantics_mixin simpl_collection */ -loadedFromPreviousSession boolean , -isTrueSeed boolean , -seed Seed , -metaMetadataName text , /*simpl_scalar xml_other_tags xml_tag */ -isDnd boolean , -termVector CompositeTermVector , -MIXINS_FIELD_NAME text , -repository MetaMetadataRepository , -MIXIN_TRANSLATION_STRING text , -mixinClasses Class[] , -MIXIN_TRANSLATIONS TranslationScope , -INITIAL_SIZE int4 , -metaMetadata MetaMetadata -); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Pdf] -CREATE TABLE Pdf ( -summary text , /*simpl_scalar */ -author text , /*simpl_scalar */ -trapped text , /*simpl_scalar */ -keywords text , /*simpl_scalar */ -contents text , /*simpl_scalar */ -subject text , /*simpl_scalar */ -creationdate text , /*simpl_scalar */ -modified text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Dlms] -CREATE TABLE Dlms ( -subject text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Bookmark] -CREATE TABLE Bookmark ( -title text , /*simpl_scalar */ -link varchar(64) , /*simpl_scalar */ -pic varchar(64) /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.Entity] -CREATE TABLE Entity ( -linkedDocument Document , -location varchar(64) , /*simpl_scalar simpl_hints */ -gist text /*simpl_scalar simpl_hints */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrTagsInteresting] -CREATE TABLE FlickrTagsInteresting ( -flickrLinkSet FlickrLink[] /*simpl_collection */ -)INHERITS (Search); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.HotSearch] -CREATE TABLE HotSearch ( -search text /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Lolz] -CREATE TABLE Lolz ( -picture varchar(64) , /*simpl_scalar */ -mightLike varchar(64) , /*simpl_scalar */ -caption text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Tumblr] -CREATE TABLE Tumblr ( -post text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.DebugMetadata] -CREATE TABLE DebugMetadata ( -newTermVector text /*simpl_scalar simpl_hints */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.Author] -CREATE TABLE Author ( -name text , /*simpl_scalar */ -affiliation text , /*simpl_scalar */ -city text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.WikipediaPageType] -CREATE TABLE WikipediaPageType ( -thumbinners Thumbinner[] , /*simpl_collection */ -paragraphs Paragraph[] , /*simpl_collection */ -categories Category[] /*simpl_collection */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.GooglePatentImage] -CREATE TABLE GooglePatentImage ( -picUrls SearchResult[] , /*simpl_collection */ -inventor text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.imdb.BirthDetail] -CREATE TABLE BirthDetail ( -yearOfBirth text , /*simpl_scalar */ -yearOfBirthLink varchar(64) , /*simpl_scalar */ -placeOfBirth text , /*simpl_scalar */ -dayOfBirthLink varchar(64) , /*simpl_scalar */ -placeOfBirthLink varchar(64) , /*simpl_scalar */ -dayOfBirth text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.imdb.ImdbChart] -CREATE TABLE ImdbChart ( -results ImdbTitle[] /*simpl_collection */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.Image] -CREATE TABLE Image ( -location varchar(64) , /*simpl_scalar */ -localLocation text , /*simpl_scalar */ -caption text /*simpl_scalar */ -)INHERITS (Media); - ---MetadataClassDescriptor[ecologylab.semantics.library.uva.Topic] -CREATE TABLE Topic ( -id int4 , /*simpl_scalar */ -anchorKeywords text , /*simpl_scalar */ -urlKeywords text , /*simpl_scalar */ -contentKeywords text , /*simpl_scalar */ -titleKeywords text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.WikipediaPage] -CREATE TABLE WikipediaPage ( -thumbinners Thumbinner[] , /*simpl_collection */ -paragraphs Paragraph[] , /*simpl_collection */ -categories Category[] , /*simpl_collection */ -mainImageSrc varchar(64) /*simpl_scalar */ -)INHERITS (WikipediaPageType); - ---MetadataClassDescriptor[ecologylab.semantics.library.imdb.ImdbGenre] -CREATE TABLE ImdbGenre ( -results ImdbTitle[] /*simpl_collection */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.DeliciousHomepage] -CREATE TABLE DeliciousHomepage ( -bookmarks Bookmark[] /*simpl_collection */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.Document] -CREATE TABLE Document ( -pageStructure text , /*simpl_scalar simpl_hints */ -title text , /*simpl_scalar */ -location varchar(64) , /*simpl_scalar */ -query text , /*simpl_scalar simpl_hints */ -description text , /*simpl_scalar */ -generation int4 /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.AcmProceeding] -CREATE TABLE AcmProceeding ( -proceedings SearchResult[] , /*simpl_collection */ -papers SearchResult[] /*simpl_collection */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Icdl] -CREATE TABLE Icdl ( -languages text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.UrbanSpoonGenre] -CREATE TABLE UrbanSpoonGenre ( -topResults SearchResult[] /*simpl_collection */ -)INHERITS (Search); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Text] -CREATE TABLE Text ( -text text /*simpl_scalar */ -)INHERITS (Media); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Category] -CREATE TABLE Category ( -catLink varchar(64) , /*simpl_scalar */ -name text /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Restaurant] -CREATE TABLE Restaurant ( -phone text , /*simpl_scalar */ -priceRange text , /*simpl_scalar */ -genres SearchResult[] , /*simpl_collection */ -link varchar(64) , /*simpl_scalar */ -map varchar(64) , /*simpl_scalar */ -rating text , /*simpl_scalar */ -pic varchar(64) /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.Link] -CREATE TABLE Link ( -link varchar(64) , /*simpl_scalar */ -heading text /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrImageDetail] -CREATE TABLE FlickrImageDetail ( -flickr_image FlickrImage /*simpl_composite */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrTag] -CREATE TABLE FlickrTag ( -tagName text , /*simpl_scalar */ -tagLink varchar(64) /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.imdb.PersonDetails] -CREATE TABLE PersonDetails ( -personImg varchar(64) , /*simpl_scalar */ -alternateNames text , /*simpl_scalar */ -triviaLink varchar(64) , /*simpl_scalar */ -titlesAsProducer ImdbTitle[] , /*simpl_collection */ -titlesForSoundtrack ImdbTitle[] , /*simpl_collection */ -titlesInDevelopment ImdbTitle[] , /*simpl_collection */ -titlesAsDirector ImdbTitle[] , /*simpl_collection */ -titlesAsActor ImdbTitle[] , /*simpl_collection */ -titlesThankedIn ImdbTitle[] , /*simpl_collection */ -awards text , /*simpl_scalar */ -trivia text , /*simpl_scalar */ -awardsLink varchar(64) , /*simpl_scalar */ -birth_detail BirthDetail , /*simpl_composite */ -miniBiography text , /*simpl_scalar */ -biographyLink varchar(64) , /*simpl_scalar */ -titlesAsSelf ImdbTitle[] /*simpl_collection */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Channel] -CREATE TYPE Channel AS ( -item Item[] /*simpl_collection simpl_nowrap */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.HotSearch] -CREATE TYPE HotSearch AS ( -search text /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.Author] -CREATE TYPE Author AS ( -name text, /*simpl_scalar */ -affiliation text, /*simpl_scalar */ -city text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrImage] -CREATE TYPE FlickrImage AS ( -browsePurl varchar(64), /*simpl_scalar */ -flickrTags FlickrTag[] /*simpl_collection */ -)INHERITS (Image); - ---MetadataClassDescriptor[ecologylab.semantics.library.imdb.BirthDetail] -CREATE TYPE BirthDetail AS ( -yearOfBirth text, /*simpl_scalar */ -yearOfBirthLink varchar(64), /*simpl_scalar */ -placeOfBirth text, /*simpl_scalar */ -dayOfBirthLink varchar(64), /*simpl_scalar */ -placeOfBirthLink varchar(64), /*simpl_scalar */ -dayOfBirth text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Paragraph] -CREATE TYPE Paragraph AS ( -anchors Anchor[], /*simpl_collection */ -paragraphText text /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Item] -CREATE TYPE Item AS ( -guid varchar(64), /*simpl_scalar simpl_hints */ -title text, /*simpl_scalar simpl_hints */ -link varchar(64) /*simpl_scalar simpl_hints */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.SearchResult] -CREATE TYPE SearchResult AS ( -link varchar(64), /*simpl_scalar */ -snippet text, /*simpl_scalar */ -heading text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.Image] -CREATE TYPE Image AS ( -location varchar(64), /*simpl_scalar */ -localLocation text, /*simpl_scalar */ -caption text /*simpl_scalar */ -)INHERITS (Media); - ---MetadataClassDescriptor[ecologylab.semantics.library.imdb.Genre] -CREATE TYPE Genre AS ( -name text, /*simpl_scalar */ -genreLink varchar(64) /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrLink] -CREATE TYPE FlickrLink AS ( -title text, /*simpl_scalar */ -link varchar(64) /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.ScholarlyArticle] -CREATE TYPE ScholarlyArticle AS ( -classifications Link[], /*simpl_collection */ -authors Author[], /*simpl_collection */ -"references" ScholarlyArticle[], /*simpl_collection */ -metadataPage varchar(64), /*simpl_scalar */ -citations ScholarlyArticle[], /*simpl_collection */ -source Source, /*simpl_composite */ -abstractField text, /*xml_tag simpl_scalar */ -keyTerms Link[] /*simpl_collection */ -)INHERITS (Pdf); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Result] -CREATE TYPE Result AS ( -summary text, /*xml_tag simpl_scalar simpl_hints */ -title text, /*xml_tag simpl_scalar simpl_hints */ -refererUrl varchar(64), /*xml_tag simpl_scalar simpl_hints */ -modificationDate int4, /*xml_tag simpl_scalar simpl_hints */ -mimeType text, /*xml_tag simpl_scalar simpl_hints */ -url varchar(64) /*xml_tag simpl_scalar simpl_hints */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Thumbinner] -CREATE TYPE Thumbinner AS ( -thumbImgCaption text, /*simpl_scalar */ -thumbImgSrc varchar(64) /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.imdb.CastMember] -CREATE TYPE CastMember AS ( -actor Entity, /*simpl_composite */ -"character" Entity /*simpl_composite */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.Source] -CREATE TYPE Source AS ( -isbn text, /*simpl_scalar */ -pages text, /*simpl_scalar */ -archive varchar(64), /*simpl_scalar */ -yearOfPublication int4 /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Category] -CREATE TYPE Category AS ( -catLink varchar(64), /*simpl_scalar */ -name text /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.imdb.ImdbTitle] -CREATE TYPE ImdbTitle AS ( -posterImg varchar(64), /*simpl_scalar */ -releaseDate text, /*simpl_scalar */ -"cast" CastMember[], /*simpl_collection */ -genres Genre[], /*simpl_collection */ -yearReleased text, /*simpl_scalar */ -writers PersonDetails[], /*simpl_collection */ -titlePhotos Image[], /*simpl_collection */ -rating text, /*simpl_scalar */ -directors PersonDetails[], /*simpl_collection */ -tagline text, /*simpl_scalar */ -plot text /*simpl_scalar */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.Link] -CREATE TYPE Link AS ( -link varchar(64), /*simpl_scalar */ -heading text /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Anchor] -CREATE TYPE Anchor AS ( -anchorText text, /*simpl_scalar */ -link varchar(64) /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrTag] -CREATE TYPE FlickrTag AS ( -tagName text, /*simpl_scalar */ -tagLink varchar(64) /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.metadata.Metadata] -CREATE TYPE Metadata AS ( -mixins Metadata[], /*semantics_mixin simpl_collection */ -loadedFromPreviousSession boolean, -isTrueSeed boolean, -seed Seed, -metaMetadataName text, /*simpl_scalar xml_other_tags xml_tag */ -isDnd boolean, -termVector CompositeTermVector, -MIXINS_FIELD_NAME text, -repository MetaMetadataRepository, -MIXIN_TRANSLATION_STRING text, -mixinClasses Class[], -MIXIN_TRANSLATIONS TranslationScope, -INITIAL_SIZE int4, -metaMetadata MetaMetadata -); - ---MetadataClassDescriptor[ecologylab.semantics.generated.library.Bookmark] -CREATE TYPE Bookmark AS ( -title text, /*simpl_scalar */ -link varchar(64), /*simpl_scalar */ -pic varchar(64) /*simpl_scalar */ -)INHERITS (Metadata); - ---MetadataClassDescriptor[ecologylab.semantics.library.imdb.PersonDetails] -CREATE TYPE PersonDetails AS ( -personImg varchar(64), /*simpl_scalar */ -alternateNames text, /*simpl_scalar */ -triviaLink varchar(64), /*simpl_scalar */ -titlesAsProducer ImdbTitle[], /*simpl_collection */ -titlesForSoundtrack ImdbTitle[], /*simpl_collection */ -titlesInDevelopment ImdbTitle[], /*simpl_collection */ -titlesAsDirector ImdbTitle[], /*simpl_collection */ -titlesAsActor ImdbTitle[], /*simpl_collection */ -titlesThankedIn ImdbTitle[], /*simpl_collection */ -awards text, /*simpl_scalar */ -trivia text, /*simpl_scalar */ -awardsLink varchar(64), /*simpl_scalar */ -birth_detail BirthDetail, /*simpl_composite */ -miniBiography text, /*simpl_scalar */ -biographyLink varchar(64), /*simpl_scalar */ -titlesAsSelf ImdbTitle[] /*simpl_collection */ -)INHERITS (Document); - ---MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.Entity] -CREATE TYPE Entity AS ( -linkedDocument Document, -location varchar(64), /*simpl_scalar simpl_hints */ -gist text /*simpl_scalar simpl_hints */ -)INHERITS (Metadata); - +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Rss] +CREATE TABLE Rss ( +channel Channel /*simpl_composite */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Search] +CREATE TABLE Search ( +searchResults SearchResult[] /*simpl_collection simpl_nowrap */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.IcdlImage] +CREATE TABLE IcdlImage ( +languages text /*simpl_scalar */ +)INHERITS (Image); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Channel] +CREATE TABLE Channel ( +item Item[] /*simpl_collection simpl_nowrap */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.YahooResultSet] +CREATE TABLE YahooResultSet ( +results Result[] /*simpl_collection simpl_nowrap */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.GooglePatent] +CREATE TABLE GooglePatent ( +claims text , /*simpl_scalar */ +picLinks SearchResult[] , /*simpl_collection */ +citations SearchResult[] , /*simpl_collection */ +abstractField text , /*simpl_scalar */ +referencedBys SearchResult[] , /*simpl_collection */ +inventor text , /*simpl_scalar */ +picLink varchar(64) /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrImage] +CREATE TABLE FlickrImage ( +browsePurl varchar(64) , /*simpl_scalar */ +flickrTags FlickrTag[] /*simpl_collection */ +)INHERITS (Image); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Paragraph] +CREATE TABLE Paragraph ( +anchors Anchor[] , /*simpl_collection */ +paragraphText text /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.DcDocument] +CREATE TABLE DcDocument ( +subject text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Item] +CREATE TABLE Item ( +guid varchar(64) , /*simpl_scalar simpl_hints */ +title text , /*simpl_scalar simpl_hints */ +link varchar(64) /*simpl_scalar simpl_hints */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.WeatherReport] +CREATE TABLE WeatherReport ( +wind text , /*simpl_scalar */ +humidity text , /*simpl_scalar */ +picUrl varchar(64) , /*simpl_scalar */ +weather text , /*simpl_scalar */ +dewPoint text , /*simpl_scalar */ +temperature text , /*simpl_scalar */ +city text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.SearchResult] +CREATE TABLE SearchResult ( +link varchar(64) , /*simpl_scalar */ +snippet text , /*simpl_scalar */ +heading text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.imdb.Genre] +CREATE TABLE Genre ( +name text , /*simpl_scalar */ +genreLink varchar(64) /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrLink] +CREATE TABLE FlickrLink ( +title text , /*simpl_scalar */ +link varchar(64) /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrAuthor] +CREATE TABLE FlickrAuthor ( +flickrLinkSet FlickrLink[] /*simpl_collection */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.ScholarlyArticle] +CREATE TABLE ScholarlyArticle ( +classifications Link[] , /*simpl_collection */ +authors Author[] , /*simpl_collection */ +"references" ScholarlyArticle[] , /*simpl_collection */ +metadataPage varchar(64) , /*simpl_scalar */ +citations ScholarlyArticle[] , /*simpl_collection */ +source Source , /*simpl_composite */ +abstractField text , /*xml_tag simpl_scalar */ +keyTerms Link[] /*simpl_collection */ +)INHERITS (Pdf); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Result] +CREATE TABLE Result ( +summary text , /*xml_tag simpl_scalar simpl_hints */ +title text , /*xml_tag simpl_scalar simpl_hints */ +refererUrl varchar(64) , /*xml_tag simpl_scalar simpl_hints */ +modificationDate int4 , /*xml_tag simpl_scalar simpl_hints */ +mimeType text , /*xml_tag simpl_scalar simpl_hints */ +url varchar(64) /*xml_tag simpl_scalar simpl_hints */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.Media] +CREATE TABLE Media ( +context text /*xml_tag simpl_scalar simpl_hints */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Artwork] +CREATE TABLE Artwork ( +artists Author[] , /*simpl_collection */ +website varchar(64) , /*simpl_scalar */ +abstractField text , /*xml_tag simpl_scalar */ +year text , /*simpl_scalar */ +medium text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.GoogleTrends] +CREATE TABLE GoogleTrends ( +hotSearches HotSearch[] /*simpl_collection simpl_nowrap */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Thumbinner] +CREATE TABLE Thumbinner ( +thumbImgCaption text , /*simpl_scalar */ +thumbImgSrc varchar(64) /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.MmArtwork] +CREATE TABLE MmArtwork ( +artists Author[] , /*simpl_collection */ +website varchar(64) , /*simpl_scalar */ +abstractField text , /*xml_tag simpl_scalar */ +year text , /*simpl_scalar */ +extendedAbstract varchar(64) , /*simpl_scalar */ +artTitle text , /*simpl_scalar */ +medium text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrSearch] +CREATE TABLE FlickrSearch ( +flickrResults FlickrImage[] /*simpl_collection */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrTags] +CREATE TABLE FlickrTags ( +flickrLinkSet FlickrLink[] /*simpl_collection */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Nsdl] +CREATE TABLE Nsdl ( +subject text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.imdb.CastMember] +CREATE TABLE CastMember ( +actor Entity , /*simpl_composite */ +"character" Entity /*simpl_composite */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.Source] +CREATE TABLE Source ( +isbn text , /*simpl_scalar */ +pages text , /*simpl_scalar */ +archive varchar(64) , /*simpl_scalar */ +yearOfPublication int4 /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.imdb.ImdbTitle] +CREATE TABLE ImdbTitle ( +posterImg varchar(64) , /*simpl_scalar */ +releaseDate text , /*simpl_scalar */ +"cast" CastMember[] , /*simpl_collection */ +genres Genre[] , /*simpl_collection */ +yearReleased text , /*simpl_scalar */ +writers PersonDetails[] , /*simpl_collection */ +titlePhotos Image[] , /*simpl_collection */ +rating text , /*simpl_scalar */ +directors PersonDetails[] , /*simpl_collection */ +tagline text , /*simpl_scalar */ +plot text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Anchor] +CREATE TABLE Anchor ( +anchorText text , /*simpl_scalar */ +link varchar(64) /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.metadata.Metadata] +CREATE TABLE Metadata ( +mixins Metadata[] , /*semantics_mixin simpl_collection */ +loadedFromPreviousSession boolean , +isTrueSeed boolean , +seed Seed , +metaMetadataName text , /*simpl_scalar xml_other_tags xml_tag */ +isDnd boolean , +termVector CompositeTermVector , +MIXINS_FIELD_NAME text , +repository MetaMetadataRepository , +MIXIN_TRANSLATION_STRING text , +mixinClasses Class[] , +MIXIN_TRANSLATIONS TranslationScope , +INITIAL_SIZE int4 , +metaMetadata MetaMetadata +); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Pdf] +CREATE TABLE Pdf ( +summary text , /*simpl_scalar */ +author text , /*simpl_scalar */ +trapped text , /*simpl_scalar */ +keywords text , /*simpl_scalar */ +contents text , /*simpl_scalar */ +subject text , /*simpl_scalar */ +creationdate text , /*simpl_scalar */ +modified text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Dlms] +CREATE TABLE Dlms ( +subject text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Bookmark] +CREATE TABLE Bookmark ( +title text , /*simpl_scalar */ +link varchar(64) , /*simpl_scalar */ +pic varchar(64) /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.Entity] +CREATE TABLE Entity ( +linkedDocument Document , +location varchar(64) , /*simpl_scalar simpl_hints */ +gist text /*simpl_scalar simpl_hints */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrTagsInteresting] +CREATE TABLE FlickrTagsInteresting ( +flickrLinkSet FlickrLink[] /*simpl_collection */ +)INHERITS (Search); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.HotSearch] +CREATE TABLE HotSearch ( +search text /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Lolz] +CREATE TABLE Lolz ( +picture varchar(64) , /*simpl_scalar */ +mightLike varchar(64) , /*simpl_scalar */ +caption text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Tumblr] +CREATE TABLE Tumblr ( +post text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.DebugMetadata] +CREATE TABLE DebugMetadata ( +newTermVector text /*simpl_scalar simpl_hints */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.Author] +CREATE TABLE Author ( +name text , /*simpl_scalar */ +affiliation text , /*simpl_scalar */ +city text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.WikipediaPageType] +CREATE TABLE WikipediaPageType ( +thumbinners Thumbinner[] , /*simpl_collection */ +paragraphs Paragraph[] , /*simpl_collection */ +categories Category[] /*simpl_collection */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.GooglePatentImage] +CREATE TABLE GooglePatentImage ( +picUrls SearchResult[] , /*simpl_collection */ +inventor text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.imdb.BirthDetail] +CREATE TABLE BirthDetail ( +yearOfBirth text , /*simpl_scalar */ +yearOfBirthLink varchar(64) , /*simpl_scalar */ +placeOfBirth text , /*simpl_scalar */ +dayOfBirthLink varchar(64) , /*simpl_scalar */ +placeOfBirthLink varchar(64) , /*simpl_scalar */ +dayOfBirth text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.imdb.ImdbChart] +CREATE TABLE ImdbChart ( +results ImdbTitle[] /*simpl_collection */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.Image] +CREATE TABLE Image ( +location varchar(64) , /*simpl_scalar */ +localLocation text , /*simpl_scalar */ +caption text /*simpl_scalar */ +)INHERITS (Media); + +--MetadataClassDescriptor[ecologylab.semantics.library.uva.Topic] +CREATE TABLE Topic ( +id int4 , /*simpl_scalar */ +anchorKeywords text , /*simpl_scalar */ +urlKeywords text , /*simpl_scalar */ +contentKeywords text , /*simpl_scalar */ +titleKeywords text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.WikipediaPage] +CREATE TABLE WikipediaPage ( +thumbinners Thumbinner[] , /*simpl_collection */ +paragraphs Paragraph[] , /*simpl_collection */ +categories Category[] , /*simpl_collection */ +mainImageSrc varchar(64) /*simpl_scalar */ +)INHERITS (WikipediaPageType); + +--MetadataClassDescriptor[ecologylab.semantics.library.imdb.ImdbGenre] +CREATE TABLE ImdbGenre ( +results ImdbTitle[] /*simpl_collection */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.DeliciousHomepage] +CREATE TABLE DeliciousHomepage ( +bookmarks Bookmark[] /*simpl_collection */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.Document] +CREATE TABLE Document ( +pageStructure text , /*simpl_scalar simpl_hints */ +title text , /*simpl_scalar */ +location varchar(64) , /*simpl_scalar */ +query text , /*simpl_scalar simpl_hints */ +description text , /*simpl_scalar */ +generation int4 /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.AcmProceeding] +CREATE TABLE AcmProceeding ( +proceedings SearchResult[] , /*simpl_collection */ +papers SearchResult[] /*simpl_collection */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Icdl] +CREATE TABLE Icdl ( +languages text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.UrbanSpoonGenre] +CREATE TABLE UrbanSpoonGenre ( +topResults SearchResult[] /*simpl_collection */ +)INHERITS (Search); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Text] +CREATE TABLE Text ( +text text /*simpl_scalar */ +)INHERITS (Media); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Category] +CREATE TABLE Category ( +catLink varchar(64) , /*simpl_scalar */ +name text /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Restaurant] +CREATE TABLE Restaurant ( +phone text , /*simpl_scalar */ +priceRange text , /*simpl_scalar */ +genres SearchResult[] , /*simpl_collection */ +link varchar(64) , /*simpl_scalar */ +map varchar(64) , /*simpl_scalar */ +rating text , /*simpl_scalar */ +pic varchar(64) /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.Link] +CREATE TABLE Link ( +link varchar(64) , /*simpl_scalar */ +heading text /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrImageDetail] +CREATE TABLE FlickrImageDetail ( +flickr_image FlickrImage /*simpl_composite */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrTag] +CREATE TABLE FlickrTag ( +tagName text , /*simpl_scalar */ +tagLink varchar(64) /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.imdb.PersonDetails] +CREATE TABLE PersonDetails ( +personImg varchar(64) , /*simpl_scalar */ +alternateNames text , /*simpl_scalar */ +triviaLink varchar(64) , /*simpl_scalar */ +titlesAsProducer ImdbTitle[] , /*simpl_collection */ +titlesForSoundtrack ImdbTitle[] , /*simpl_collection */ +titlesInDevelopment ImdbTitle[] , /*simpl_collection */ +titlesAsDirector ImdbTitle[] , /*simpl_collection */ +titlesAsActor ImdbTitle[] , /*simpl_collection */ +titlesThankedIn ImdbTitle[] , /*simpl_collection */ +awards text , /*simpl_scalar */ +trivia text , /*simpl_scalar */ +awardsLink varchar(64) , /*simpl_scalar */ +birth_detail BirthDetail , /*simpl_composite */ +miniBiography text , /*simpl_scalar */ +biographyLink varchar(64) , /*simpl_scalar */ +titlesAsSelf ImdbTitle[] /*simpl_collection */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Channel] +CREATE TYPE Channel AS ( +item Item[] /*simpl_collection simpl_nowrap */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.HotSearch] +CREATE TYPE HotSearch AS ( +search text /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.Author] +CREATE TYPE Author AS ( +name text, /*simpl_scalar */ +affiliation text, /*simpl_scalar */ +city text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrImage] +CREATE TYPE FlickrImage AS ( +browsePurl varchar(64), /*simpl_scalar */ +flickrTags FlickrTag[] /*simpl_collection */ +)INHERITS (Image); + +--MetadataClassDescriptor[ecologylab.semantics.library.imdb.BirthDetail] +CREATE TYPE BirthDetail AS ( +yearOfBirth text, /*simpl_scalar */ +yearOfBirthLink varchar(64), /*simpl_scalar */ +placeOfBirth text, /*simpl_scalar */ +dayOfBirthLink varchar(64), /*simpl_scalar */ +placeOfBirthLink varchar(64), /*simpl_scalar */ +dayOfBirth text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Paragraph] +CREATE TYPE Paragraph AS ( +anchors Anchor[], /*simpl_collection */ +paragraphText text /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Item] +CREATE TYPE Item AS ( +guid varchar(64), /*simpl_scalar simpl_hints */ +title text, /*simpl_scalar simpl_hints */ +link varchar(64) /*simpl_scalar simpl_hints */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.SearchResult] +CREATE TYPE SearchResult AS ( +link varchar(64), /*simpl_scalar */ +snippet text, /*simpl_scalar */ +heading text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.Image] +CREATE TYPE Image AS ( +location varchar(64), /*simpl_scalar */ +localLocation text, /*simpl_scalar */ +caption text /*simpl_scalar */ +)INHERITS (Media); + +--MetadataClassDescriptor[ecologylab.semantics.library.imdb.Genre] +CREATE TYPE Genre AS ( +name text, /*simpl_scalar */ +genreLink varchar(64) /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrLink] +CREATE TYPE FlickrLink AS ( +title text, /*simpl_scalar */ +link varchar(64) /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.ScholarlyArticle] +CREATE TYPE ScholarlyArticle AS ( +classifications Link[], /*simpl_collection */ +authors Author[], /*simpl_collection */ +"references" ScholarlyArticle[], /*simpl_collection */ +metadataPage varchar(64), /*simpl_scalar */ +citations ScholarlyArticle[], /*simpl_collection */ +source Source, /*simpl_composite */ +abstractField text, /*xml_tag simpl_scalar */ +keyTerms Link[] /*simpl_collection */ +)INHERITS (Pdf); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Result] +CREATE TYPE Result AS ( +summary text, /*xml_tag simpl_scalar simpl_hints */ +title text, /*xml_tag simpl_scalar simpl_hints */ +refererUrl varchar(64), /*xml_tag simpl_scalar simpl_hints */ +modificationDate int4, /*xml_tag simpl_scalar simpl_hints */ +mimeType text, /*xml_tag simpl_scalar simpl_hints */ +url varchar(64) /*xml_tag simpl_scalar simpl_hints */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Thumbinner] +CREATE TYPE Thumbinner AS ( +thumbImgCaption text, /*simpl_scalar */ +thumbImgSrc varchar(64) /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.imdb.CastMember] +CREATE TYPE CastMember AS ( +actor Entity, /*simpl_composite */ +"character" Entity /*simpl_composite */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.Source] +CREATE TYPE Source AS ( +isbn text, /*simpl_scalar */ +pages text, /*simpl_scalar */ +archive varchar(64), /*simpl_scalar */ +yearOfPublication int4 /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Category] +CREATE TYPE Category AS ( +catLink varchar(64), /*simpl_scalar */ +name text /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.imdb.ImdbTitle] +CREATE TYPE ImdbTitle AS ( +posterImg varchar(64), /*simpl_scalar */ +releaseDate text, /*simpl_scalar */ +"cast" CastMember[], /*simpl_collection */ +genres Genre[], /*simpl_collection */ +yearReleased text, /*simpl_scalar */ +writers PersonDetails[], /*simpl_collection */ +titlePhotos Image[], /*simpl_collection */ +rating text, /*simpl_scalar */ +directors PersonDetails[], /*simpl_collection */ +tagline text, /*simpl_scalar */ +plot text /*simpl_scalar */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.library.scholarlyPublication.Link] +CREATE TYPE Link AS ( +link varchar(64), /*simpl_scalar */ +heading text /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Anchor] +CREATE TYPE Anchor AS ( +anchorText text, /*simpl_scalar */ +link varchar(64) /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.flickr.FlickrTag] +CREATE TYPE FlickrTag AS ( +tagName text, /*simpl_scalar */ +tagLink varchar(64) /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.metadata.Metadata] +CREATE TYPE Metadata AS ( +mixins Metadata[], /*semantics_mixin simpl_collection */ +loadedFromPreviousSession boolean, +isTrueSeed boolean, +seed Seed, +metaMetadataName text, /*simpl_scalar xml_other_tags xml_tag */ +isDnd boolean, +termVector CompositeTermVector, +MIXINS_FIELD_NAME text, +repository MetaMetadataRepository, +MIXIN_TRANSLATION_STRING text, +mixinClasses Class[], +MIXIN_TRANSLATIONS TranslationScope, +INITIAL_SIZE int4, +metaMetadata MetaMetadata +); + +--MetadataClassDescriptor[ecologylab.semantics.generated.library.Bookmark] +CREATE TYPE Bookmark AS ( +title text, /*simpl_scalar */ +link varchar(64), /*simpl_scalar */ +pic varchar(64) /*simpl_scalar */ +)INHERITS (Metadata); + +--MetadataClassDescriptor[ecologylab.semantics.library.imdb.PersonDetails] +CREATE TYPE PersonDetails AS ( +personImg varchar(64), /*simpl_scalar */ +alternateNames text, /*simpl_scalar */ +triviaLink varchar(64), /*simpl_scalar */ +titlesAsProducer ImdbTitle[], /*simpl_collection */ +titlesForSoundtrack ImdbTitle[], /*simpl_collection */ +titlesInDevelopment ImdbTitle[], /*simpl_collection */ +titlesAsDirector ImdbTitle[], /*simpl_collection */ +titlesAsActor ImdbTitle[], /*simpl_collection */ +titlesThankedIn ImdbTitle[], /*simpl_collection */ +awards text, /*simpl_scalar */ +trivia text, /*simpl_scalar */ +awardsLink varchar(64), /*simpl_scalar */ +birth_detail BirthDetail, /*simpl_composite */ +miniBiography text, /*simpl_scalar */ +biographyLink varchar(64), /*simpl_scalar */ +titlesAsSelf ImdbTitle[] /*simpl_collection */ +)INHERITS (Document); + +--MetadataClassDescriptor[ecologylab.semantics.metadata.builtins.Entity] +CREATE TYPE Entity AS ( +linkedDocument Document, +location varchar(64), /*simpl_scalar simpl_hints */ +gist text /*simpl_scalar simpl_hints */ +)INHERITS (Metadata); + diff --git a/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/ChannelTest.java b/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/ChannelTest.java index 15ae7b56..3a71d78b 100644 --- a/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/ChannelTest.java +++ b/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/ChannelTest.java @@ -1,140 +1,140 @@ -package ecologylab.translators.sql.testing.ecologylabXmlTest; - -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.annotations.DbHint; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_db; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_inherit; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.formatenums.StringFormat; -import ecologylab.serialization.library.rss.RssTranslations; - -/** - * RSS parser channel element {@link ecologylab.serialization.ElementState ElementState} declaration. - * Used with most RSS versions. - * - * @author andruid - */ -public @simpl_inherit class ChannelTest extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_db(references="ItemTest", value = - {DbHint.NOT_NULL, DbHint.PRIMARY_KEY}) String title; - - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_db({DbHint.NOT_NULL, DbHint.UNIQUE}) String description; - /** - * Could point to an HTML rendering of the feed. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_db({DbHint.UNIQUE}) ParsedURL link; - - @simpl_nowrap @simpl_collection("item") @simpl_db({DbHint.NOT_NULL}) ArrayList items; - - /** - * @return Returns the description. - */ - public String getDescription() - { - return description; - } - /** - * @param description The description to set. - */ - public void setDescription(String description) - { - this.description = description; - } - /** - * @return Returns the title. - */ - public String getTitle() - { - return title; - } - /** - * @param title The title to set. - */ - public void setTitle(String title) - { - this.title = title; - } - - /** - * @return Returns the link. - */ - public ParsedURL getLink() - { - return link; - } - /** - * @param link The link to set. - */ - public void setLink(ParsedURL link) - { - this.link = link; - } - - public ArrayList getItems() - { - return items; - } - - public void add(ItemTest item) - { - if (items == null) - items = new ArrayList(); - items.add(item); - } - - public ItemTest get(int i) - { - return items == null ? null : items.get(i); - } - public int size() - { - return items == null ? 0 : items.size(); - } - - public static void main(String[] s) - { - testTranslateTo(); - } - private static void testTranslateTo() - { - ChannelTest c = new ChannelTest(); - ItemTest i1 = new ItemTest(); - i1.author = "zach"; - i1.title = "it is called rogue!"; - i1.link = ParsedURL.getAbsolute("http://ecologylab.cs.tamu.edu/rogue/"); - i1.description = "its a game"; - ItemTest i2 = new ItemTest(); - i2.author = "andruid"; - i2.title = "it is called cf!"; - i2.description = "its a creativity support tool"; - c.items = new ArrayList(); - c.items. add(i1); - c.items.add(i2); - try - { - StringBuilder buffy = new StringBuilder(); - - SimplTypesScope.serialize(c, buffy, StringFormat.XML); - System.out.println(buffy); - System.out.println('\n'); - ElementState c2 = (ElementState) RssTranslations.get().deserialize(buffy, StringFormat.XML); - - SimplTypesScope.serialize(c2, System.out, StringFormat.XML); -// println(c.translateToXML()); - } catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } -} +package ecologylab.translators.sql.testing.ecologylabXmlTest; + +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.annotations.DbHint; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_db; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_inherit; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.formatenums.StringFormat; +import ecologylab.serialization.library.rss.RssTranslations; + +/** + * RSS parser channel element {@link ecologylab.serialization.ElementState ElementState} declaration. + * Used with most RSS versions. + * + * @author andruid + */ +public @simpl_inherit class ChannelTest extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_db(references="ItemTest", value = + {DbHint.NOT_NULL, DbHint.PRIMARY_KEY}) String title; + + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_db({DbHint.NOT_NULL, DbHint.UNIQUE}) String description; + /** + * Could point to an HTML rendering of the feed. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) @simpl_db({DbHint.UNIQUE}) ParsedURL link; + + @simpl_nowrap @simpl_collection("item") @simpl_db({DbHint.NOT_NULL}) ArrayList items; + + /** + * @return Returns the description. + */ + public String getDescription() + { + return description; + } + /** + * @param description The description to set. + */ + public void setDescription(String description) + { + this.description = description; + } + /** + * @return Returns the title. + */ + public String getTitle() + { + return title; + } + /** + * @param title The title to set. + */ + public void setTitle(String title) + { + this.title = title; + } + + /** + * @return Returns the link. + */ + public ParsedURL getLink() + { + return link; + } + /** + * @param link The link to set. + */ + public void setLink(ParsedURL link) + { + this.link = link; + } + + public ArrayList getItems() + { + return items; + } + + public void add(ItemTest item) + { + if (items == null) + items = new ArrayList(); + items.add(item); + } + + public ItemTest get(int i) + { + return items == null ? null : items.get(i); + } + public int size() + { + return items == null ? 0 : items.size(); + } + + public static void main(String[] s) + { + testTranslateTo(); + } + private static void testTranslateTo() + { + ChannelTest c = new ChannelTest(); + ItemTest i1 = new ItemTest(); + i1.author = "zach"; + i1.title = "it is called rogue!"; + i1.link = ParsedURL.getAbsolute("http://ecologylab.cs.tamu.edu/rogue/"); + i1.description = "its a game"; + ItemTest i2 = new ItemTest(); + i2.author = "andruid"; + i2.title = "it is called cf!"; + i2.description = "its a creativity support tool"; + c.items = new ArrayList(); + c.items. add(i1); + c.items.add(i2); + try + { + StringBuilder buffy = new StringBuilder(); + + SimplTypesScope.serialize(c, buffy, StringFormat.XML); + System.out.println(buffy); + System.out.println('\n'); + ElementState c2 = (ElementState) RssTranslations.get().deserialize(buffy, StringFormat.XML); + + SimplTypesScope.serialize(c2, System.out, StringFormat.XML); +// println(c.translateToXML()); + } catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/ItemTest.java b/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/ItemTest.java index f4f857a6..a7a4713e 100644 --- a/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/ItemTest.java +++ b/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/ItemTest.java @@ -1,114 +1,114 @@ -package ecologylab.translators.sql.testing.ecologylabXmlTest; - -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.annotations.Hint; -import ecologylab.serialization.annotations.simpl_collection; -import ecologylab.serialization.annotations.simpl_hints; -import ecologylab.serialization.annotations.simpl_nowrap; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.library.dc.Dc; -import ecologylab.serialization.library.feedburner.Feedburner; -import ecologylab.serialization.library.media.Media; - -/** - * RSS parser ite element {@link ecologylab.serialization.ElementState ElementState} declaration. - * Used with most (perhaps all) RSS versions. - *

- * Includes support for funky included namespace content, such as DublinCore, Yahoo Media, and Feedburner. - * - * @author andruid - */ -public class ItemTest extends ElementState -{ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; - /** - * This version of link often has a special url with rss in it. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; - /** - * This seems to be the version of link that users want to see. - */ - @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL guid; - @simpl_scalar @simpl_hints(Hint.XML_LEAF) String author; - - @simpl_nowrap - @simpl_collection("category") ArrayList categorySet; - - public ItemTest() - { - super(); - } - public ItemTest(String title) - { - super(); - this.title = title; - } - /** - * @return Returns the author. - */ - public String getAuthor() - { - return author; - } - - /** - * @param author The author to set. - */ - public void setAuthor(String author) - { - this.author = author; - } - - /** - * @return Returns the description. - */ - public String getDescription() - { - return description; - } - - /** - * @param description The description to set. - */ - public void setDescription(String description) - { - this.description = description; - } - - /** - * @return Returns the link. - */ - public ParsedURL getLink() - { - return link; - } - - /** - * @param link The link to set. - */ - public void setLink(ParsedURL link) - { - this.link = link; - } - - /** - * @return Returns the title. - */ - public String getTitle() - { - return title; - } - - /** - * @param title The title to set. - */ - public void setTitle(String title) - { - this.title = title; - } - -} +package ecologylab.translators.sql.testing.ecologylabXmlTest; + +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.annotations.Hint; +import ecologylab.serialization.annotations.simpl_collection; +import ecologylab.serialization.annotations.simpl_hints; +import ecologylab.serialization.annotations.simpl_nowrap; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.library.dc.Dc; +import ecologylab.serialization.library.feedburner.Feedburner; +import ecologylab.serialization.library.media.Media; + +/** + * RSS parser ite element {@link ecologylab.serialization.ElementState ElementState} declaration. + * Used with most (perhaps all) RSS versions. + *

+ * Includes support for funky included namespace content, such as DublinCore, Yahoo Media, and Feedburner. + * + * @author andruid + */ +public class ItemTest extends ElementState +{ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String title; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String description; + /** + * This version of link often has a special url with rss in it. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL link; + /** + * This seems to be the version of link that users want to see. + */ + @simpl_scalar @simpl_hints(Hint.XML_LEAF) ParsedURL guid; + @simpl_scalar @simpl_hints(Hint.XML_LEAF) String author; + + @simpl_nowrap + @simpl_collection("category") ArrayList categorySet; + + public ItemTest() + { + super(); + } + public ItemTest(String title) + { + super(); + this.title = title; + } + /** + * @return Returns the author. + */ + public String getAuthor() + { + return author; + } + + /** + * @param author The author to set. + */ + public void setAuthor(String author) + { + this.author = author; + } + + /** + * @return Returns the description. + */ + public String getDescription() + { + return description; + } + + /** + * @param description The description to set. + */ + public void setDescription(String description) + { + this.description = description; + } + + /** + * @return Returns the link. + */ + public ParsedURL getLink() + { + return link; + } + + /** + * @param link The link to set. + */ + public void setLink(ParsedURL link) + { + this.link = link; + } + + /** + * @return Returns the title. + */ + public String getTitle() + { + return title; + } + + /** + * @param title The title to set. + */ + public void setTitle(String title) + { + this.title = title; + } + +} diff --git a/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/RssStateTest.java b/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/RssStateTest.java index 8f896271..3c52dc21 100644 --- a/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/RssStateTest.java +++ b/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/RssStateTest.java @@ -1,198 +1,198 @@ -package ecologylab.translators.sql.testing.ecologylabXmlTest; - -import java.io.File; -import java.util.ArrayList; - -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.annotations.DbHint; -import ecologylab.serialization.annotations.simpl_composite; -import ecologylab.serialization.annotations.simpl_db; -import ecologylab.serialization.annotations.simpl_scalar; -import ecologylab.serialization.library.feedburner.Feedburner; -import ecologylab.serialization.library.media.Media; -import ecologylab.serialization.library.media.Thumbnail; -import ecologylab.serialization.library.rss.RssTranslations; - -/** - * {@link ecologylab.serialization.ElementState ElementState} for the root element of the RSS parser. - * In particular, this supports RSS versions such as .91, .92, .93, .94, and 2.0. - * - * @author andruid - */ -public class RssStateTest extends ElementState -{ - @simpl_scalar @simpl_db({DbHint.NOT_NULL}) float version; - - @simpl_composite @simpl_db({DbHint.PRIMARY_KEY}) ChannelTest channel; - - /** - * @return Returns the channel. - */ - public ChannelTest getChannel() - { - return channel; - } - - /** - * @param channel The channel to set. - */ - public void setChannel(ChannelTest channel) - { - this.channel = channel; - } - - /** - * @return Returns the version. - */ - public float getVersion() - { - return version; - } - - /** - * @param version The version to set. - */ - public void setVersion(float version) - { - this.version = version; - } - - public static final ParsedURL NYT_TECH_FEED = ParsedURL.getAbsolute("http://www.nytimes.com/services/xml/rss/nyt/Technology.xml"); - public static final ParsedURL CNN_TOP_FEED = ParsedURL.getAbsolute("http://rss.cnn.com/rss/cnn_topstories.rss"); - - public static final ParsedURL BBC_FRONT_FEED = ParsedURL.getAbsolute("http://news.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml"); - - public static final ParsedURL ABC_SPORTS_FEED = ParsedURL.getAbsolute("http://my.abcnews.go.com/rsspublic/sports_rss20.xml"); - - public static final ParsedURL FLICKR_FEED = ParsedURL.getAbsolute("http://www.flickr.com/services/feeds/photos_public.gne?format=rss_200&tags=sunset"); - - public static final ParsedURL DELICIOUS_FEED = ParsedURL.getAbsolute("http://del.icio.us/rss/andruid/"); - - public static final String ABC_EXAMPLE = - "\r\n" + - " \r\n" + - "\r\n" + - "\r\n" + - " \r\n" + - " \r\n" + - " \r\n" + - " \r\n" + - "\r\n" + - " Pats Steamroll Bills, Move to 10-0\r\n" + - " http://feeds.feedburner.com/~r/AbcNews_Sports/~3/186994604/wireStory\r\n" + - " \r\n" + - " Lead by Tom Brady and Randy Moss, Pats scored TDs on their first 7 possessions.<img src=\"http://feeds.feedburner.com/~r/AbcNews_Sports/~4/186994604\" height=\"1\" width=\"1\"/> \r\n" + - "" + - "\r\n" + - "\r\n" + - "\r\n"; - - public static final String NS_EXAMPLE = "\r\n" + - " \r\n" + - " \r\n" + - " \r\n" + - " Musharraf \'will quit army soon\' \r\n" + - " Pakistan\'s attorney general says he expects President Musharraf to resign as army head before 1 December. \r\n" + - " http://news.bbc.co.uk/go/rss/-/2/hi/south_asia/7096381.stm \r\n" + - " http://news.bbc.co.uk/2/hi/south_asia/7096381.stm \r\n" + - " Thu, 15 Nov 2007 13:58:24 GMT \r\n" + - " South Asia \r\n" + - " \r\n" + - " \r\n" + - " Canadian stun gun death on video \r\n" + - " A video is released of a Polish immigrant\'s death after he was stun gunned by police at Vancouver airport. \r\n" + - " http://news.bbc.co.uk/go/rss/-/2/hi/americas/7095875.stm \r\n" + - " http://news.bbc.co.uk/2/hi/americas/7095875.stm \r\n" + - " Thu, 15 Nov 2007 11:18:54 GMT \r\n" + - " Americas \r\n" + - " \r\n" + - " \r\n" + - " \r\n" + - ""; - - public static final String FEEDBURNER_EXAMPlE = - "\r\n" + - "\r\n" + - "CNN.com\r\n" + - "\r\n" + - "\r\n" + - "http://www.cnn.com/2007/POLITICS/11/16/congress.crandallmine/index.html\r\n" + - "Utah mine owner faces Senate panel subpoena\r\n" + - "\r\n" + - "http://www.cnn.com/2007/POLITICS/11/16/congress.crandallmine/index.html\r\n" + - "http://rss.cnn.com/~r/rss/cnn_topstories/~3/186060716/index.html\r\n" + - "A Senate subcommittee probing this summer\'s deadly Utah mine disaster has subpoenaed the mine\'s co-owner, ranking member Sen. Arlen Specter said Friday.\r\n" + - "Fri, 16 Nov 2007 19:53:04 EST\r\n" + - "\r\n" + - "\r\n" + - "\r\n" + - "\r\n"; - - public static final String FLICKR_EXAMPLE = - "\r\n" + - " \r\n" + - " Photos from everyone tagged water\r\n" + - " http://www.flickr.com/photos/tags/water/\r\n" + - " \r\n" + - " Fire-Worksing\r\n" + - " Fire-Works\r\n" + - " http://www.flickr.com/photos/meemz/2161548299/\r\n" + - " Fire-Works\r\n" + - "\r\n" + - " \r\n" + - "\r\n" + - "\r\n"; - - public static final String ITEM_EXAMPLE = - " \r\n" + - " Fire-Works\r\n" + - " \r\n" + - " Fire-Works\r\n" + - " http://www.flickr.com/photos/meemz/2161548299/\r\n" + -// " Fire-Works\r\n" + - "\r\n" + - " \r\n" + - " Photos from everyone tagged water\r\n" + - " http://www.flickr.com/photos/tags/water/\r\n" + - "\r\n"; - - public static final String NABEEL_TEST = - ""+ - ""+ - " title.Nabeel"+ - " description.Student"+ - " http://www.google.com/ig"+ - " "+ - " "+ - " Item.title.Nabeel"+ - " Item.description.Nabeel"+ - " http://www.google.com/ig"+ - " http://www.google.com/ig"+ - " Item.author.Nabeel"+ - " newCat 0"+ - " newCat 1"+ - " "+ - " "+ - " Item.title.Nabeel"+ - " Item.description.Nabeel"+ - " http://www.google.com/ig"+ - " http://www.google.com/ig"+ - " Item.author.Nabeel"+ - " newCat 0"+ - " newCat 1"+ - " "+ - " "+ - ""+ - ""; - - public static final File outputFile = new File("/temp/rss.xml"); - - -} +package ecologylab.translators.sql.testing.ecologylabXmlTest; + +import java.io.File; +import java.util.ArrayList; + +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.annotations.DbHint; +import ecologylab.serialization.annotations.simpl_composite; +import ecologylab.serialization.annotations.simpl_db; +import ecologylab.serialization.annotations.simpl_scalar; +import ecologylab.serialization.library.feedburner.Feedburner; +import ecologylab.serialization.library.media.Media; +import ecologylab.serialization.library.media.Thumbnail; +import ecologylab.serialization.library.rss.RssTranslations; + +/** + * {@link ecologylab.serialization.ElementState ElementState} for the root element of the RSS parser. + * In particular, this supports RSS versions such as .91, .92, .93, .94, and 2.0. + * + * @author andruid + */ +public class RssStateTest extends ElementState +{ + @simpl_scalar @simpl_db({DbHint.NOT_NULL}) float version; + + @simpl_composite @simpl_db({DbHint.PRIMARY_KEY}) ChannelTest channel; + + /** + * @return Returns the channel. + */ + public ChannelTest getChannel() + { + return channel; + } + + /** + * @param channel The channel to set. + */ + public void setChannel(ChannelTest channel) + { + this.channel = channel; + } + + /** + * @return Returns the version. + */ + public float getVersion() + { + return version; + } + + /** + * @param version The version to set. + */ + public void setVersion(float version) + { + this.version = version; + } + + public static final ParsedURL NYT_TECH_FEED = ParsedURL.getAbsolute("http://www.nytimes.com/services/xml/rss/nyt/Technology.xml"); + public static final ParsedURL CNN_TOP_FEED = ParsedURL.getAbsolute("http://rss.cnn.com/rss/cnn_topstories.rss"); + + public static final ParsedURL BBC_FRONT_FEED = ParsedURL.getAbsolute("http://news.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml"); + + public static final ParsedURL ABC_SPORTS_FEED = ParsedURL.getAbsolute("http://my.abcnews.go.com/rsspublic/sports_rss20.xml"); + + public static final ParsedURL FLICKR_FEED = ParsedURL.getAbsolute("http://www.flickr.com/services/feeds/photos_public.gne?format=rss_200&tags=sunset"); + + public static final ParsedURL DELICIOUS_FEED = ParsedURL.getAbsolute("http://del.icio.us/rss/andruid/"); + + public static final String ABC_EXAMPLE = + "\r\n" + + " \r\n" + + "\r\n" + + "\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + "\r\n" + + " Pats Steamroll Bills, Move to 10-0\r\n" + + " http://feeds.feedburner.com/~r/AbcNews_Sports/~3/186994604/wireStory\r\n" + + " \r\n" + + " Lead by Tom Brady and Randy Moss, Pats scored TDs on their first 7 possessions.<img src=\"http://feeds.feedburner.com/~r/AbcNews_Sports/~4/186994604\" height=\"1\" width=\"1\"/> \r\n" + + "" + + "\r\n" + + "\r\n" + + "\r\n"; + + public static final String NS_EXAMPLE = "\r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + " Musharraf \'will quit army soon\' \r\n" + + " Pakistan\'s attorney general says he expects President Musharraf to resign as army head before 1 December. \r\n" + + " http://news.bbc.co.uk/go/rss/-/2/hi/south_asia/7096381.stm \r\n" + + " http://news.bbc.co.uk/2/hi/south_asia/7096381.stm \r\n" + + " Thu, 15 Nov 2007 13:58:24 GMT \r\n" + + " South Asia \r\n" + + " \r\n" + + " \r\n" + + " Canadian stun gun death on video \r\n" + + " A video is released of a Polish immigrant\'s death after he was stun gunned by police at Vancouver airport. \r\n" + + " http://news.bbc.co.uk/go/rss/-/2/hi/americas/7095875.stm \r\n" + + " http://news.bbc.co.uk/2/hi/americas/7095875.stm \r\n" + + " Thu, 15 Nov 2007 11:18:54 GMT \r\n" + + " Americas \r\n" + + " \r\n" + + " \r\n" + + " \r\n" + + ""; + + public static final String FEEDBURNER_EXAMPlE = + "\r\n" + + "\r\n" + + "CNN.com\r\n" + + "\r\n" + + "\r\n" + + "http://www.cnn.com/2007/POLITICS/11/16/congress.crandallmine/index.html\r\n" + + "Utah mine owner faces Senate panel subpoena\r\n" + + "\r\n" + + "http://www.cnn.com/2007/POLITICS/11/16/congress.crandallmine/index.html\r\n" + + "http://rss.cnn.com/~r/rss/cnn_topstories/~3/186060716/index.html\r\n" + + "A Senate subcommittee probing this summer\'s deadly Utah mine disaster has subpoenaed the mine\'s co-owner, ranking member Sen. Arlen Specter said Friday.\r\n" + + "Fri, 16 Nov 2007 19:53:04 EST\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n"; + + public static final String FLICKR_EXAMPLE = + "\r\n" + + " \r\n" + + " Photos from everyone tagged water\r\n" + + " http://www.flickr.com/photos/tags/water/\r\n" + + " \r\n" + + " Fire-Worksing\r\n" + + " Fire-Works\r\n" + + " http://www.flickr.com/photos/meemz/2161548299/\r\n" + + " Fire-Works\r\n" + + "\r\n" + + " \r\n" + + "\r\n" + + "\r\n"; + + public static final String ITEM_EXAMPLE = + " \r\n" + + " Fire-Works\r\n" + + " \r\n" + + " Fire-Works\r\n" + + " http://www.flickr.com/photos/meemz/2161548299/\r\n" + +// " Fire-Works\r\n" + + "\r\n" + + " \r\n" + + " Photos from everyone tagged water\r\n" + + " http://www.flickr.com/photos/tags/water/\r\n" + + "\r\n"; + + public static final String NABEEL_TEST = + ""+ + ""+ + " title.Nabeel"+ + " description.Student"+ + " http://www.google.com/ig"+ + " "+ + " "+ + " Item.title.Nabeel"+ + " Item.description.Nabeel"+ + " http://www.google.com/ig"+ + " http://www.google.com/ig"+ + " Item.author.Nabeel"+ + " newCat 0"+ + " newCat 1"+ + " "+ + " "+ + " Item.title.Nabeel"+ + " Item.description.Nabeel"+ + " http://www.google.com/ig"+ + " http://www.google.com/ig"+ + " Item.author.Nabeel"+ + " newCat 0"+ + " newCat 1"+ + " "+ + " "+ + ""+ + ""; + + public static final File outputFile = new File("/temp/rss.xml"); + + +} diff --git a/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/RssTranslationsTest.java b/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/RssTranslationsTest.java index e4a87f4b..3f113ad9 100644 --- a/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/RssTranslationsTest.java +++ b/simplTranslators/src/ecologylab/translators/sql/testing/ecologylabXmlTest/RssTranslationsTest.java @@ -1,90 +1,90 @@ -package ecologylab.translators.sql.testing.ecologylabXmlTest; - -import ecologylab.generic.Debug; -import ecologylab.net.ParsedURL; -import ecologylab.serialization.ElementState; -import ecologylab.serialization.SIMPLTranslationException; -import ecologylab.serialization.SimplTypesScope; -import ecologylab.serialization.formatenums.StringFormat; - -/** - * Translations for all RSS parsing. - * - * @author andruid - */ -public class RssTranslationsTest -extends Debug -{ - private static final String TRANSLATION_SPACE_NAME = "rss"; - - public static final Class TRANSLATIONS[] = - { - RssStateTest.class, - ChannelTest.class, - ItemTest.class, - -// Dc.class, -// -// -// RDFState.class, - }; - /* - public static final TranslationScope INHERITED_TRANSLATIONS[] = - { - Media.getTranslations(), - - }; - - public static final NameSpaceDecl[] NAME_SPACE_DECLS = - { - new NameSpaceDecl("http://search.yahoo.com/mrss/", Media.class, Media.getTranslations()), - new NameSpaceDecl("http://rssnamespace.org/feedburner/ext/1.0", Feedburner.class, Feedburner.get()), - new NameSpaceDecl("http://purl.org/dc/elements/1.1/", Dc.class, Dc.get()), - - }; - */ - /** - * Just prevent anyone from new'ing this. - */ - private RssTranslationsTest() - { - } - - public static SimplTypesScope get() - { - return SimplTypesScope.get(TRANSLATION_SPACE_NAME, /* NAME_SPACE_DECLS,INHERITED_TRANSLATIONS, */ - TRANSLATIONS); - } - - public static final String OUT = ""; - - static final ParsedURL FLICKR_PURL = ParsedURL.getAbsolute("http://www.flickr.com/services/feeds/photos_public.gne?format=rss_200&tags=freedom", ""); - - public static void main(String[] args) - { - SimplTypesScope tScope = get(); - - try - { - StringBuilder buffy = new StringBuilder(); - - - SimplTypesScope.serialize(tScope, buffy, StringFormat.XML); - System.out.println('\n'); - - ElementState translated = (ElementState) SimplTypesScope.getBasicTranslations().deserialize(buffy, StringFormat.XML); - //ElementState.translateFromXMLCharSequence(OUT, TranslationScope.getBasicTranslations()); - - - SimplTypesScope.serialize(translated, System.out, StringFormat.XML); - System.out.println('\n'); - } - catch (SIMPLTranslationException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - System.out.println("\n"); - } - -} +package ecologylab.translators.sql.testing.ecologylabXmlTest; + +import ecologylab.generic.Debug; +import ecologylab.net.ParsedURL; +import ecologylab.serialization.ElementState; +import ecologylab.serialization.SIMPLTranslationException; +import ecologylab.serialization.SimplTypesScope; +import ecologylab.serialization.formatenums.StringFormat; + +/** + * Translations for all RSS parsing. + * + * @author andruid + */ +public class RssTranslationsTest +extends Debug +{ + private static final String TRANSLATION_SPACE_NAME = "rss"; + + public static final Class TRANSLATIONS[] = + { + RssStateTest.class, + ChannelTest.class, + ItemTest.class, + +// Dc.class, +// +// +// RDFState.class, + }; + /* + public static final TranslationScope INHERITED_TRANSLATIONS[] = + { + Media.getTranslations(), + + }; + + public static final NameSpaceDecl[] NAME_SPACE_DECLS = + { + new NameSpaceDecl("http://search.yahoo.com/mrss/", Media.class, Media.getTranslations()), + new NameSpaceDecl("http://rssnamespace.org/feedburner/ext/1.0", Feedburner.class, Feedburner.get()), + new NameSpaceDecl("http://purl.org/dc/elements/1.1/", Dc.class, Dc.get()), + + }; + */ + /** + * Just prevent anyone from new'ing this. + */ + private RssTranslationsTest() + { + } + + public static SimplTypesScope get() + { + return SimplTypesScope.get(TRANSLATION_SPACE_NAME, /* NAME_SPACE_DECLS,INHERITED_TRANSLATIONS, */ + TRANSLATIONS); + } + + public static final String OUT = ""; + + static final ParsedURL FLICKR_PURL = ParsedURL.getAbsolute("http://www.flickr.com/services/feeds/photos_public.gne?format=rss_200&tags=freedom", ""); + + public static void main(String[] args) + { + SimplTypesScope tScope = get(); + + try + { + StringBuilder buffy = new StringBuilder(); + + + SimplTypesScope.serialize(tScope, buffy, StringFormat.XML); + System.out.println('\n'); + + ElementState translated = (ElementState) SimplTypesScope.getBasicTranslations().deserialize(buffy, StringFormat.XML); + //ElementState.translateFromXMLCharSequence(OUT, TranslationScope.getBasicTranslations()); + + + SimplTypesScope.serialize(translated, System.out, StringFormat.XML); + System.out.println('\n'); + } + catch (SIMPLTranslationException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + System.out.println("\n"); + } + +} diff --git a/simplTranslators/src/simpl/translation/api/BaseTranslator.java b/simplTranslators/src/simpl/translation/api/BaseTranslator.java index 452c5263..c8ce9b5e 100644 --- a/simplTranslators/src/simpl/translation/api/BaseTranslator.java +++ b/simplTranslators/src/simpl/translation/api/BaseTranslator.java @@ -1,75 +1,75 @@ -package simpl.translation.api; - -import java.util.HashSet; -import java.util.Set; -import java.util.Collection; - - -/** - * This is the base class for any Translator that needs to aggregate dependencies. - * It does some of the common work for collecting dependencies, - * implementors simply need to implement "AggregateDependencies" to grab dependencies - * generated by the translator. - * - * MetaInformation may translate any number of Parameters. Each parameter creates a dependency... - * Within a MetaInformation translator's "AggregateDependencies()", - * one should call each of the ParameterTranslator's getDependencies() method. - * @author Tom - * - */ -public abstract class BaseTranslator implements DependencyTracker { - /** - * Holds onto the dependencies tracked by this translator. - */ - private Set trackedDependencies = new HashSet(); - - @Override - /** - * Adds a dependency to this translator. - * @param dependency the full package/path name of the dependency - */ - public void addDependency(String dependency) { - this.trackedDependencies.add(dependency); - } - - /** - * Adds a collection of dependencies to the translator. - * @param dependencies A collection of full package/path names to dependencies - */ - @Override - public void addDependencies(Collection dependencies) { - this.trackedDependencies.addAll(dependencies); - } - - /** - * AggregateDependencies collects all of the dependencies that - * translators invoked within a given translator have accrued. - * - * For Example: - * MetaInformation may translate any number of Parameters. Each parameter creates a dependency... - * Within a MetaInformation translator's "AggregateDependencies()", - * one should call each of the ParameterTranslator's getDependencies() method. - */ - public abstract Set aggregateDependencies(); - - @Override - /** - * Gets all of the dependencies for this translator; - * It adds all of the dependencies tracked to the results of aggregateDependencies(), - * then returns the depenendency set. - * - * This call is mutable (because it makes the API's a bit cleaner), - * Calling this call immediately after a call to getDependencies() will return an empty set. - */ - public Set getDependencies() { - this.trackedDependencies.addAll(aggregateDependencies()); - Set toReturn = new HashSet(); - toReturn.addAll(this.trackedDependencies); - - //reset this trackedDependencies for the next getDependency() call. - this.trackedDependencies = new HashSet(); - - // return the dependencies we had. - return toReturn; - } -} +package simpl.translation.api; + +import java.util.HashSet; +import java.util.Set; +import java.util.Collection; + + +/** + * This is the base class for any Translator that needs to aggregate dependencies. + * It does some of the common work for collecting dependencies, + * implementors simply need to implement "AggregateDependencies" to grab dependencies + * generated by the translator. + * + * MetaInformation may translate any number of Parameters. Each parameter creates a dependency... + * Within a MetaInformation translator's "AggregateDependencies()", + * one should call each of the ParameterTranslator's getDependencies() method. + * @author Tom + * + */ +public abstract class BaseTranslator implements DependencyTracker { + /** + * Holds onto the dependencies tracked by this translator. + */ + private Set trackedDependencies = new HashSet(); + + @Override + /** + * Adds a dependency to this translator. + * @param dependency the full package/path name of the dependency + */ + public void addDependency(String dependency) { + this.trackedDependencies.add(dependency); + } + + /** + * Adds a collection of dependencies to the translator. + * @param dependencies A collection of full package/path names to dependencies + */ + @Override + public void addDependencies(Collection dependencies) { + this.trackedDependencies.addAll(dependencies); + } + + /** + * AggregateDependencies collects all of the dependencies that + * translators invoked within a given translator have accrued. + * + * For Example: + * MetaInformation may translate any number of Parameters. Each parameter creates a dependency... + * Within a MetaInformation translator's "AggregateDependencies()", + * one should call each of the ParameterTranslator's getDependencies() method. + */ + public abstract Set aggregateDependencies(); + + @Override + /** + * Gets all of the dependencies for this translator; + * It adds all of the dependencies tracked to the results of aggregateDependencies(), + * then returns the depenendency set. + * + * This call is mutable (because it makes the API's a bit cleaner), + * Calling this call immediately after a call to getDependencies() will return an empty set. + */ + public Set getDependencies() { + this.trackedDependencies.addAll(aggregateDependencies()); + Set toReturn = new HashSet(); + toReturn.addAll(this.trackedDependencies); + + //reset this trackedDependencies for the next getDependency() call. + this.trackedDependencies = new HashSet(); + + // return the dependencies we had. + return toReturn; + } +} diff --git a/simplTranslators/src/simpl/translation/api/ClassTranslator.java b/simplTranslators/src/simpl/translation/api/ClassTranslator.java index de9276d3..e3b38c15 100644 --- a/simplTranslators/src/simpl/translation/api/ClassTranslator.java +++ b/simplTranslators/src/simpl/translation/api/ClassTranslator.java @@ -1,8 +1,8 @@ -package simpl.translation.api; - -import ecologylab.serialization.ClassDescriptor; - - -public abstract class ClassTranslator extends BaseTranslator { - public abstract SourceAppender translateClass(ClassDescriptor cd); -} +package simpl.translation.api; + +import ecologylab.serialization.ClassDescriptor; + + +public abstract class ClassTranslator extends BaseTranslator { + public abstract SourceAppender translateClass(ClassDescriptor cd); +} diff --git a/simplTranslators/src/simpl/translation/api/CommentTranslator.java b/simplTranslators/src/simpl/translation/api/CommentTranslator.java index b6e3b106..22313e50 100644 --- a/simplTranslators/src/simpl/translation/api/CommentTranslator.java +++ b/simplTranslators/src/simpl/translation/api/CommentTranslator.java @@ -1,15 +1,15 @@ -package simpl.translation.api; - -/** - * This interface translates lines of comments into source comments - */ -public interface CommentTranslator { - /** - * Translates a set of comments into a comment. - * If there are multiple lines, should use the idiomatic - * representation of a multi-line comment in the target language. - * @param comments A collection of comments - * @return A SourceAppender containing entries for the comments. - */ - public SourceAppender translateDocComment(String... comments); +package simpl.translation.api; + +/** + * This interface translates lines of comments into source comments + */ +public interface CommentTranslator { + /** + * Translates a set of comments into a comment. + * If there are multiple lines, should use the idiomatic + * representation of a multi-line comment in the target language. + * @param comments A collection of comments + * @return A SourceAppender containing entries for the comments. + */ + public SourceAppender translateDocComment(String... comments); } \ No newline at end of file diff --git a/simplTranslators/src/simpl/translation/api/DependencyTracker.java b/simplTranslators/src/simpl/translation/api/DependencyTracker.java index ecee8340..b144a386 100644 --- a/simplTranslators/src/simpl/translation/api/DependencyTracker.java +++ b/simplTranslators/src/simpl/translation/api/DependencyTracker.java @@ -1,35 +1,35 @@ -package simpl.translation.api; - -import java.util.Collection; -import java.util.Set; - -/** - * An interface that represents an entity that tracks source dependencies. - */ -public interface DependencyTracker { - /** - * Adds a dependency to this DependencyTracker - * @param dependency The full path/package name to the dependency - */ - void addDependency(String dependency); - - /** - * Adds a collection of dependencies to this DependencyTracker - * @param dependencies A collection of full path/package names to dependencies - */ - void addDependencies(Collection dependencies); - - /** - * Aggregate the dependencies that a given tracker may have. - * (For instance, a field has a metainformationtranslator. - * Grab the dependencies from the metainformation translator in the aggregateDependencies call - * @return - */ - Set aggregateDependencies(); - /** - * Aggregates the dependencies that other trackers have, and then combines them with the dependencies - * tracked by this tracker. - * @return - */ - Set getDependencies(); -} +package simpl.translation.api; + +import java.util.Collection; +import java.util.Set; + +/** + * An interface that represents an entity that tracks source dependencies. + */ +public interface DependencyTracker { + /** + * Adds a dependency to this DependencyTracker + * @param dependency The full path/package name to the dependency + */ + void addDependency(String dependency); + + /** + * Adds a collection of dependencies to this DependencyTracker + * @param dependencies A collection of full path/package names to dependencies + */ + void addDependencies(Collection dependencies); + + /** + * Aggregate the dependencies that a given tracker may have. + * (For instance, a field has a metainformationtranslator. + * Grab the dependencies from the metainformation translator in the aggregateDependencies call + * @return + */ + Set aggregateDependencies(); + /** + * Aggregates the dependencies that other trackers have, and then combines them with the dependencies + * tracked by this tracker. + * @return + */ + Set getDependencies(); +} diff --git a/simplTranslators/src/simpl/translation/api/DependencyTranslator.java b/simplTranslators/src/simpl/translation/api/DependencyTranslator.java index cc5d87a9..7a9287f0 100644 --- a/simplTranslators/src/simpl/translation/api/DependencyTranslator.java +++ b/simplTranslators/src/simpl/translation/api/DependencyTranslator.java @@ -1,15 +1,15 @@ -package simpl.translation.api; - -import java.util.Collection; -import java.util.List; - -/** - * Translates a list of dependency to the appropriate set of usings / imports for a given language. - * Also manages global dependencies for a certain language. - * @author twhite - */ -public interface DependencyTranslator { - List getGlobalDependencies(); - SourceAppender translateDependency(String s); - SourceAppender translateClassDependencies(Collection a); -} +package simpl.translation.api; + +import java.util.Collection; +import java.util.List; + +/** + * Translates a list of dependency to the appropriate set of usings / imports for a given language. + * Also manages global dependencies for a certain language. + * @author twhite + */ +public interface DependencyTranslator { + List getGlobalDependencies(); + SourceAppender translateDependency(String s); + SourceAppender translateClassDependencies(Collection a); +} diff --git a/simplTranslators/src/simpl/translation/api/FieldTranslator.java b/simplTranslators/src/simpl/translation/api/FieldTranslator.java index 81714c12..843f332c 100644 --- a/simplTranslators/src/simpl/translation/api/FieldTranslator.java +++ b/simplTranslators/src/simpl/translation/api/FieldTranslator.java @@ -1,26 +1,26 @@ -package simpl.translation.api; - -import java.util.List; - -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; - -/** - * An interface that encompasses translation of FieldDescriptors to source code in some language. - */ -public abstract class FieldTranslator extends BaseTranslator{ - /** - * Translates a single field into source code - * @param context The ClassDescriptor that the Field is contained within - * @param fieldDescriptor The FieldDescriptor to translate into source representation - * @return A SourceAppender containing the representation of this Field - */ - public abstract SourceAppender translateField(ClassDescriptor context, FieldDescriptor fieldDescriptor); - - /** - * Translates all fields for a ClassDescriptor into their source representations. - * @param context The ClassDescriptor that the Field is contained within - * @return A SourceAppender containing the source represntation of all fields within the Class - */ - public abstract SourceAppender translateFields(ClassDescriptor context); -} +package simpl.translation.api; + +import java.util.List; + +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; + +/** + * An interface that encompasses translation of FieldDescriptors to source code in some language. + */ +public abstract class FieldTranslator extends BaseTranslator{ + /** + * Translates a single field into source code + * @param context The ClassDescriptor that the Field is contained within + * @param fieldDescriptor The FieldDescriptor to translate into source representation + * @return A SourceAppender containing the representation of this Field + */ + public abstract SourceAppender translateField(ClassDescriptor context, FieldDescriptor fieldDescriptor); + + /** + * Translates all fields for a ClassDescriptor into their source representations. + * @param context The ClassDescriptor that the Field is contained within + * @return A SourceAppender containing the source represntation of all fields within the Class + */ + public abstract SourceAppender translateFields(ClassDescriptor context); +} diff --git a/simplTranslators/src/simpl/translation/api/GenericTypeVariableTranslator.java b/simplTranslators/src/simpl/translation/api/GenericTypeVariableTranslator.java index 3ab060a0..7d27f1e4 100644 --- a/simplTranslators/src/simpl/translation/api/GenericTypeVariableTranslator.java +++ b/simplTranslators/src/simpl/translation/api/GenericTypeVariableTranslator.java @@ -1,10 +1,10 @@ -package simpl.translation.api; - -import java.util.List; - -import ecologylab.serialization.GenericTypeVar; - -public abstract class GenericTypeVariableTranslator extends BaseTranslator { - public abstract SourceAppender translateBoundedGenericType(List genericTypeVariables); - public abstract SourceAppender translateUnboundedGenericType(List genericTypeVariables); -} +package simpl.translation.api; + +import java.util.List; + +import ecologylab.serialization.GenericTypeVar; + +public abstract class GenericTypeVariableTranslator extends BaseTranslator { + public abstract SourceAppender translateBoundedGenericType(List genericTypeVariables); + public abstract SourceAppender translateUnboundedGenericType(List genericTypeVariables); +} diff --git a/simplTranslators/src/simpl/translation/api/LanguageCore.java b/simplTranslators/src/simpl/translation/api/LanguageCore.java index 52040e10..6f576ba2 100644 --- a/simplTranslators/src/simpl/translation/api/LanguageCore.java +++ b/simplTranslators/src/simpl/translation/api/LanguageCore.java @@ -1,16 +1,16 @@ -package simpl.translation.api; - -/** - * An interface that represents core aspects of a given language. - * Primarily just checks keywords - * - */ -public interface LanguageCore { - /** - * Determines if a String S is a reserved keyword in this language - * @param s The string to check - * @return True if it is a keyword, false otherwise. - * - */ - boolean isKeyword(String s); -} +package simpl.translation.api; + +/** + * An interface that represents core aspects of a given language. + * Primarily just checks keywords + * + */ +public interface LanguageCore { + /** + * Determines if a String S is a reserved keyword in this language + * @param s The string to check + * @return True if it is a keyword, false otherwise. + * + */ + boolean isKeyword(String s); +} diff --git a/simplTranslators/src/simpl/translation/api/MetaInformationTranslator.java b/simplTranslators/src/simpl/translation/api/MetaInformationTranslator.java index 8e4ed32f..d0da97c9 100644 --- a/simplTranslators/src/simpl/translation/api/MetaInformationTranslator.java +++ b/simplTranslators/src/simpl/translation/api/MetaInformationTranslator.java @@ -1,19 +1,19 @@ -package simpl.translation.api; - -import ecologylab.serialization.MetaInformation; - - -/** - * A component that translates "MetaInformation" (that is, classes representing annotations or attributes in a target lanugage) - * into source code for a language - * @author twhite - * - */ -public abstract class MetaInformationTranslator extends BaseTranslator{ - /** - * Creates a source representation of MetaInformation - * @param metaInfo A Description of MetaInformation - * @return Source representation of the MetaInformation. - */ - public abstract SourceAppender translateMetaInformation(MetaInformation metaInfo); -} +package simpl.translation.api; + +import ecologylab.serialization.MetaInformation; + + +/** + * A component that translates "MetaInformation" (that is, classes representing annotations or attributes in a target lanugage) + * into source code for a language + * @author twhite + * + */ +public abstract class MetaInformationTranslator extends BaseTranslator{ + /** + * Creates a source representation of MetaInformation + * @param metaInfo A Description of MetaInformation + * @return Source representation of the MetaInformation. + */ + public abstract SourceAppender translateMetaInformation(MetaInformation metaInfo); +} diff --git a/simplTranslators/src/simpl/translation/api/ParameterTranslator.java b/simplTranslators/src/simpl/translation/api/ParameterTranslator.java index c11100f7..a05c1a14 100644 --- a/simplTranslators/src/simpl/translation/api/ParameterTranslator.java +++ b/simplTranslators/src/simpl/translation/api/ParameterTranslator.java @@ -1,30 +1,30 @@ -package simpl.translation.api; - -import java.util.List; - -import simpl.descriptors.ParameterDescriptor; - -/** - * Translates a parameter into a source representation - */ -public abstract class ParameterTranslator extends BaseTranslator{ - /** - * Translates a single parameter into a String - * @param d A description of a parameter - * @return The parameter as a string - */ - public abstract String translateParameter(ParameterDescriptor d); - - /** - * Translates a set of parameters into a parameter list. - * @param d An ordered list of paramters. (Method Formals, MetaInformation values, etc) - * @return The representation of the parameters, as a string. For example( a,b,c) or (a=10, b=20) - */ - public abstract String translateParameterList(List d); - /** - * Obtains the value of a given paramter object; used for serializing default values or metaInformation values. - * @param argValue - * @return - */ - public abstract String translateParameterValue(Object argValue); -} +package simpl.translation.api; + +import java.util.List; + +import simpl.descriptors.ParameterDescriptor; + +/** + * Translates a parameter into a source representation + */ +public abstract class ParameterTranslator extends BaseTranslator{ + /** + * Translates a single parameter into a String + * @param d A description of a parameter + * @return The parameter as a string + */ + public abstract String translateParameter(ParameterDescriptor d); + + /** + * Translates a set of parameters into a parameter list. + * @param d An ordered list of paramters. (Method Formals, MetaInformation values, etc) + * @return The representation of the parameters, as a string. For example( a,b,c) or (a=10, b=20) + */ + public abstract String translateParameterList(List d); + /** + * Obtains the value of a given paramter object; used for serializing default values or metaInformation values. + * @param argValue + * @return + */ + public abstract String translateParameterValue(Object argValue); +} diff --git a/simplTranslators/src/simpl/translation/api/SourceAppender.java b/simplTranslators/src/simpl/translation/api/SourceAppender.java index 492b1938..238e9655 100644 --- a/simplTranslators/src/simpl/translation/api/SourceAppender.java +++ b/simplTranslators/src/simpl/translation/api/SourceAppender.java @@ -1,57 +1,57 @@ -package simpl.translation.api; - - /** - * Represents an object that appends source code. - */ -public interface SourceAppender { - - /** - * Sets the configuration for this Source Appender - * @param s - */ - void setConfiguration(SourceAppenderConfiguration s); - - /** - * Gets the configuration for this SourceAppender - * @return - */ - SourceAppenderConfiguration getConfiguration(); - - - /** - * Implicitly converts the string into a SourceEntry - */ - SourceAppender append(String s); - - /** - * Appends a source entry to the SourceAppender - * @param s The entry of source code to append. (Like public class ClassName) - * @return the soruce appender; this is a fluent API - */ - SourceAppender append(SourceEntry s); - - /** - * Appends the contents of one SourceAppender to another - * @param s The source appender. {a, b, etc.} - * @return {thisSourceAppender, a, b, etc.} - */ - SourceAppender append(SourceAppender s); - - /** - * Converts this appender to the source representation - * @return A string representing the source code constructed - */ - String toSource(); - - /** - * Obtains the entries in this sourceAppender - * @return - */ - Iterable getEntries(); - - /** - * Obatins the number of entries in this sourceAppender - * @return - */ - int size(); -} +package simpl.translation.api; + + /** + * Represents an object that appends source code. + */ +public interface SourceAppender { + + /** + * Sets the configuration for this Source Appender + * @param s + */ + void setConfiguration(SourceAppenderConfiguration s); + + /** + * Gets the configuration for this SourceAppender + * @return + */ + SourceAppenderConfiguration getConfiguration(); + + + /** + * Implicitly converts the string into a SourceEntry + */ + SourceAppender append(String s); + + /** + * Appends a source entry to the SourceAppender + * @param s The entry of source code to append. (Like public class ClassName) + * @return the soruce appender; this is a fluent API + */ + SourceAppender append(SourceEntry s); + + /** + * Appends the contents of one SourceAppender to another + * @param s The source appender. {a, b, etc.} + * @return {thisSourceAppender, a, b, etc.} + */ + SourceAppender append(SourceAppender s); + + /** + * Converts this appender to the source representation + * @return A string representing the source code constructed + */ + String toSource(); + + /** + * Obtains the entries in this sourceAppender + * @return + */ + Iterable getEntries(); + + /** + * Obatins the number of entries in this sourceAppender + * @return + */ + int size(); +} diff --git a/simplTranslators/src/simpl/translation/api/SourceAppenderConfiguration.java b/simplTranslators/src/simpl/translation/api/SourceAppenderConfiguration.java index e410c295..eb47c0da 100644 --- a/simplTranslators/src/simpl/translation/api/SourceAppenderConfiguration.java +++ b/simplTranslators/src/simpl/translation/api/SourceAppenderConfiguration.java @@ -1,110 +1,110 @@ -package simpl.translation.api; - - -public class SourceAppenderConfiguration { - - /** - * Character that represents a tab - */ - private String tabCharacter; - - /** - * Character that represents a linebreak - */ - private String lineBreak; - - /** - * Character that represents the start of a block - */ - private String blockStart; - - /** - * Chracter that represents the end of a block - */ - private String blockEnd; - - /** - * Configures with default values. - */ - public SourceAppenderConfiguration() - { - // Initialize all values to defaults. - this.tabCharacter = "\t"; - this.lineBreak = "\r\n"; - this.blockStart = "{"; - this.blockEnd = "}"; - } - - /** - * Configures a SourceAppender with chosen values. - * @param tab Tab Character - * @param line LineBreak character - * @param blockStart Beginning of a block - * @param blockEnd ending of a block - */ - public SourceAppenderConfiguration(String tab, String line, String blockStart, String blockEnd) - { - this.tabCharacter = tab; - this.lineBreak = line; - this.blockStart = blockStart; - this.blockEnd = blockEnd; - } - - public String getTabCharacter() { - return tabCharacter; - } - - public void setTabCharacter(String tabCharacter) { - this.tabCharacter = tabCharacter; - } - - public String getLineBreak() { - return lineBreak; - } - - public void setLineBreak(String lineBreak) { - this.lineBreak = lineBreak; - } - - public String getBlockStart() { - return blockStart; - } - - public void setBlockStart(String blockStart) { - this.blockStart = blockStart; - } - - public String getBlockEnd() { - return blockEnd; - } - - public void setBlockEnd(String blockEnd) { - this.blockEnd = blockEnd; - } - - public String translateSourceEntry(SourceEntry entry) - { - if(entry.isDelimiter()) - { - if(entry.equals(SourceEntry.TAB)) - { - return this.getTabCharacter(); - } - if(entry.equals(SourceEntry.BREAK)) - { - return this.getLineBreak(); - } - if(entry.equals(SourceEntry.BLOCK_BEGIN)) - { - return this.getBlockStart(); - } - if(entry.equals(SourceEntry.BLOCK_END)) - { - return this.getBlockEnd(); - } - throw new RuntimeException("Invalid SourceEntry. Expected valid delimmiter but did not get it."); - }else{ - return entry.getLineOfSource(); - } - } -} +package simpl.translation.api; + + +public class SourceAppenderConfiguration { + + /** + * Character that represents a tab + */ + private String tabCharacter; + + /** + * Character that represents a linebreak + */ + private String lineBreak; + + /** + * Character that represents the start of a block + */ + private String blockStart; + + /** + * Chracter that represents the end of a block + */ + private String blockEnd; + + /** + * Configures with default values. + */ + public SourceAppenderConfiguration() + { + // Initialize all values to defaults. + this.tabCharacter = "\t"; + this.lineBreak = "\r\n"; + this.blockStart = "{"; + this.blockEnd = "}"; + } + + /** + * Configures a SourceAppender with chosen values. + * @param tab Tab Character + * @param line LineBreak character + * @param blockStart Beginning of a block + * @param blockEnd ending of a block + */ + public SourceAppenderConfiguration(String tab, String line, String blockStart, String blockEnd) + { + this.tabCharacter = tab; + this.lineBreak = line; + this.blockStart = blockStart; + this.blockEnd = blockEnd; + } + + public String getTabCharacter() { + return tabCharacter; + } + + public void setTabCharacter(String tabCharacter) { + this.tabCharacter = tabCharacter; + } + + public String getLineBreak() { + return lineBreak; + } + + public void setLineBreak(String lineBreak) { + this.lineBreak = lineBreak; + } + + public String getBlockStart() { + return blockStart; + } + + public void setBlockStart(String blockStart) { + this.blockStart = blockStart; + } + + public String getBlockEnd() { + return blockEnd; + } + + public void setBlockEnd(String blockEnd) { + this.blockEnd = blockEnd; + } + + public String translateSourceEntry(SourceEntry entry) + { + if(entry.isDelimiter()) + { + if(entry.equals(SourceEntry.TAB)) + { + return this.getTabCharacter(); + } + if(entry.equals(SourceEntry.BREAK)) + { + return this.getLineBreak(); + } + if(entry.equals(SourceEntry.BLOCK_BEGIN)) + { + return this.getBlockStart(); + } + if(entry.equals(SourceEntry.BLOCK_END)) + { + return this.getBlockEnd(); + } + throw new RuntimeException("Invalid SourceEntry. Expected valid delimmiter but did not get it."); + }else{ + return entry.getLineOfSource(); + } + } +} diff --git a/simplTranslators/src/simpl/translation/api/SourceCodeAppender.java b/simplTranslators/src/simpl/translation/api/SourceCodeAppender.java index cc10ce67..ecf6801e 100644 --- a/simplTranslators/src/simpl/translation/api/SourceCodeAppender.java +++ b/simplTranslators/src/simpl/translation/api/SourceCodeAppender.java @@ -1,118 +1,118 @@ -package simpl.translation.api; - -import java.util.LinkedList; -import java.util.List; - -public class SourceCodeAppender implements SourceAppender { - - private SourceAppenderConfiguration ourConfig; - - public SourceCodeAppender() - { - // use default config. - this.ourConfig = new SourceAppenderConfiguration(); - } - - private List ourEntries = new LinkedList(); - - @Override - public void setConfiguration(SourceAppenderConfiguration s) { - this.ourConfig = s; - } - - @Override - public SourceAppenderConfiguration getConfiguration() { - // TODO Auto-generated method stub - return this.ourConfig; - } - - @Override - public SourceAppender append(String s) { - // TODO Auto-generated method stub - SourceEntry se = new SourceEntry(s); - ourEntries.add(se); - return this; - } - - @Override - public SourceAppender append(SourceEntry s) { - // TODO Auto-generated method stub - ourEntries.add(s); - return this; - } - - @Override - public SourceAppender append(SourceAppender s) { - // TODO Auto-generated method stub - for(SourceEntry se : s.getEntries()) - { - this.append(se); - } - return this; - } - - @Override - public Iterable getEntries() - { - return this.ourEntries; - } - - - - private String repeatTab(int times) - { - String tab = ourConfig.translateSourceEntry(SourceEntry.TAB); - - String tabbed = ""; - for(int i = 0; i < times; i++){ - tabbed = tabbed + tab; - } - - return tabbed; - } - - - @Override - public String toSource() { - // This is where the magic happens! :D - int tabDepth = 0; - - StringBuilder sb = new StringBuilder(); - // In general: - // Each line is tabCharacter * tabDepth Times + LineofSource + lineBreak; - for(SourceEntry se : this.ourEntries) - { - if(se.equals(SourceEntry.BLOCK_END)) - { - tabDepth--; - } - - sb.append(repeatTab(tabDepth)); - sb.append(ourConfig.translateSourceEntry(se)); - - if(!se.equals(SourceEntry.BREAK)) - { - sb.append(ourConfig.translateSourceEntry(SourceEntry.BREAK)); - } - - if(se.equals(SourceEntry.BLOCK_BEGIN)) - { - tabDepth++; - } - - - if(se.equals(SourceEntry.TAB)) - { - throw new RuntimeException("Attempting to append tab; reconsider this behavior."); - } - } - - return sb.toString(); - } - - @Override - public int size() - { - return this.ourEntries.size(); - } -} +package simpl.translation.api; + +import java.util.LinkedList; +import java.util.List; + +public class SourceCodeAppender implements SourceAppender { + + private SourceAppenderConfiguration ourConfig; + + public SourceCodeAppender() + { + // use default config. + this.ourConfig = new SourceAppenderConfiguration(); + } + + private List ourEntries = new LinkedList(); + + @Override + public void setConfiguration(SourceAppenderConfiguration s) { + this.ourConfig = s; + } + + @Override + public SourceAppenderConfiguration getConfiguration() { + // TODO Auto-generated method stub + return this.ourConfig; + } + + @Override + public SourceAppender append(String s) { + // TODO Auto-generated method stub + SourceEntry se = new SourceEntry(s); + ourEntries.add(se); + return this; + } + + @Override + public SourceAppender append(SourceEntry s) { + // TODO Auto-generated method stub + ourEntries.add(s); + return this; + } + + @Override + public SourceAppender append(SourceAppender s) { + // TODO Auto-generated method stub + for(SourceEntry se : s.getEntries()) + { + this.append(se); + } + return this; + } + + @Override + public Iterable getEntries() + { + return this.ourEntries; + } + + + + private String repeatTab(int times) + { + String tab = ourConfig.translateSourceEntry(SourceEntry.TAB); + + String tabbed = ""; + for(int i = 0; i < times; i++){ + tabbed = tabbed + tab; + } + + return tabbed; + } + + + @Override + public String toSource() { + // This is where the magic happens! :D + int tabDepth = 0; + + StringBuilder sb = new StringBuilder(); + // In general: + // Each line is tabCharacter * tabDepth Times + LineofSource + lineBreak; + for(SourceEntry se : this.ourEntries) + { + if(se.equals(SourceEntry.BLOCK_END)) + { + tabDepth--; + } + + sb.append(repeatTab(tabDepth)); + sb.append(ourConfig.translateSourceEntry(se)); + + if(!se.equals(SourceEntry.BREAK)) + { + sb.append(ourConfig.translateSourceEntry(SourceEntry.BREAK)); + } + + if(se.equals(SourceEntry.BLOCK_BEGIN)) + { + tabDepth++; + } + + + if(se.equals(SourceEntry.TAB)) + { + throw new RuntimeException("Attempting to append tab; reconsider this behavior."); + } + } + + return sb.toString(); + } + + @Override + public int size() + { + return this.ourEntries.size(); + } +} diff --git a/simplTranslators/src/simpl/translation/api/SourceEntry.java b/simplTranslators/src/simpl/translation/api/SourceEntry.java index 055947aa..b3b5fb61 100644 --- a/simplTranslators/src/simpl/translation/api/SourceEntry.java +++ b/simplTranslators/src/simpl/translation/api/SourceEntry.java @@ -1,109 +1,109 @@ -package simpl.translation.api; - -/** - * A class representing a single entry of sourcecode - * Examples include "public class Something" - * or "void SomeFunction()" - * - * Translators generate sourceEntries, the SourceAppender handles the task of tabbing and line breaking - * So that code is generated with nice indentation, etc. - * @author twhite - * - */ -public class SourceEntry { - String lineOfSource = ""; - public boolean isBreak() { - return isBreak; - } - - public boolean isBlockBegin() { - return isBlockBegin; - } - - public boolean isBlockEnd() { - return isBlockEnd; - } - - public boolean isTab() { - return isTab; - } - - boolean isBreak = false; - boolean isBlockBegin = false; - boolean isBlockEnd = false; - boolean isTab = false; - - public static SourceEntry BREAK = new SourceEntry(true, false, false, false); - public static SourceEntry BLOCK_BEGIN = new SourceEntry(false, true, false, false); - public static SourceEntry BLOCK_END = new SourceEntry(false, false, true, false); - public static SourceEntry TAB = new SourceEntry(false, false, false, true); - - private SourceEntry(boolean isBreak, boolean isBlockBegin, boolean isBlockEnd, boolean isTab){ - this.isBreak = isBreak; - this.isBlockBegin = isBlockBegin; - this.isBlockEnd = isBlockEnd; - this.isTab = isTab; - }; - - public SourceEntry(String lineOfSource) - { - this.lineOfSource = lineOfSource; - } - - public String getLineOfSource() - { - return this.lineOfSource; - } - - public boolean isDelimiter() - { - return isBreak || isBlockEnd || isBlockBegin || isTab; - } - - @Override - public boolean equals(Object obj) { - // TODO Auto-generated method stub - if(obj != null && obj instanceof SourceEntry) - { - SourceEntry other = (SourceEntry)obj; - - if(this.isDelimiter()) - { - if(other.isDelimiter()) - { - // Compare the delimiter values. All must match. - return ((this.isTab() == other.isTab())&& - (this.isBreak() == other.isBreak())&& - (this.isBlockBegin() == other.isBlockBegin())&& - (this.isBlockEnd() == other.isBlockEnd())); - }else{ - return false; - } - }else{ - if(other.isDelimiter()) - { - return false; - }else{ - return this.getLineOfSource().equals(other.getLineOfSource()); - } - } - }else{ - return false; - } - } - - @Override - public int hashCode() - { - if(lineOfSource.isEmpty()) - { - int b = isBreak ? 1:0; - int bb = isBlockBegin ? 2:0; - int be = isBlockEnd ? 4:0; - int tt = isTab ? 8:0; - return b+bb+be+tt; - }else{ - return lineOfSource.hashCode(); - } - } -} +package simpl.translation.api; + +/** + * A class representing a single entry of sourcecode + * Examples include "public class Something" + * or "void SomeFunction()" + * + * Translators generate sourceEntries, the SourceAppender handles the task of tabbing and line breaking + * So that code is generated with nice indentation, etc. + * @author twhite + * + */ +public class SourceEntry { + String lineOfSource = ""; + public boolean isBreak() { + return isBreak; + } + + public boolean isBlockBegin() { + return isBlockBegin; + } + + public boolean isBlockEnd() { + return isBlockEnd; + } + + public boolean isTab() { + return isTab; + } + + boolean isBreak = false; + boolean isBlockBegin = false; + boolean isBlockEnd = false; + boolean isTab = false; + + public static SourceEntry BREAK = new SourceEntry(true, false, false, false); + public static SourceEntry BLOCK_BEGIN = new SourceEntry(false, true, false, false); + public static SourceEntry BLOCK_END = new SourceEntry(false, false, true, false); + public static SourceEntry TAB = new SourceEntry(false, false, false, true); + + private SourceEntry(boolean isBreak, boolean isBlockBegin, boolean isBlockEnd, boolean isTab){ + this.isBreak = isBreak; + this.isBlockBegin = isBlockBegin; + this.isBlockEnd = isBlockEnd; + this.isTab = isTab; + }; + + public SourceEntry(String lineOfSource) + { + this.lineOfSource = lineOfSource; + } + + public String getLineOfSource() + { + return this.lineOfSource; + } + + public boolean isDelimiter() + { + return isBreak || isBlockEnd || isBlockBegin || isTab; + } + + @Override + public boolean equals(Object obj) { + // TODO Auto-generated method stub + if(obj != null && obj instanceof SourceEntry) + { + SourceEntry other = (SourceEntry)obj; + + if(this.isDelimiter()) + { + if(other.isDelimiter()) + { + // Compare the delimiter values. All must match. + return ((this.isTab() == other.isTab())&& + (this.isBreak() == other.isBreak())&& + (this.isBlockBegin() == other.isBlockBegin())&& + (this.isBlockEnd() == other.isBlockEnd())); + }else{ + return false; + } + }else{ + if(other.isDelimiter()) + { + return false; + }else{ + return this.getLineOfSource().equals(other.getLineOfSource()); + } + } + }else{ + return false; + } + } + + @Override + public int hashCode() + { + if(lineOfSource.isEmpty()) + { + int b = isBreak ? 1:0; + int bb = isBlockBegin ? 2:0; + int be = isBlockEnd ? 4:0; + int tt = isTab ? 8:0; + return b+bb+be+tt; + }else{ + return lineOfSource.hashCode(); + } + } +} diff --git a/simplTranslators/src/simpl/translators/java/JavaClassTranslator.java b/simplTranslators/src/simpl/translators/java/JavaClassTranslator.java index 054a6e31..64b08040 100644 --- a/simplTranslators/src/simpl/translators/java/JavaClassTranslator.java +++ b/simplTranslators/src/simpl/translators/java/JavaClassTranslator.java @@ -1,66 +1,66 @@ -package simpl.translators.java; - - -import java.util.HashSet; -import java.util.Set; - -import ecologylab.appframework.types.prefs.MetaPrefString; -import ecologylab.serialization.ClassDescriptor; - -import simpl.translation.api.ClassTranslator; -import simpl.translation.api.CommentTranslator; -import simpl.translation.api.FieldTranslator; -import simpl.translation.api.MetaInformationTranslator; -import simpl.translation.api.SourceAppender; -import simpl.translation.api.SourceCodeAppender; -import simpl.translation.api.SourceEntry; - -public class JavaClassTranslator extends ClassTranslator{ - - private FieldTranslator fieldTranslator = new JavaFieldTranslator(); - private CommentTranslator commentTranslator = new JavaCommentTranslator(); - private MetaInformationTranslator metaInfoTranslator = new JavaMetaInformationTranslator(); - - public SourceAppender translateDefaultConstructor(ClassDescriptor cd) - { - SourceAppender appender = new SourceCodeAppender(); - appender.append("public " + cd.getDescribedClassSimpleName() + "()"); - appender.append(SourceEntry.BLOCK_BEGIN); - appender.append(SourceEntry.BLOCK_END); - return appender; - } - - @Override - public SourceAppender translateClass(ClassDescriptor cd) { - - SourceAppender appender = new SourceCodeAppender(); - - StringBuilder appendable = new StringBuilder(); - - appender.append(commentTranslator.translateDocComment(cd.getComment())); - - appender.append("public class " + cd.getDescribedClassSimpleName()); - appender.append(SourceEntry.BLOCK_BEGIN); - - appender.append(fieldTranslator.translateFields(cd)); - - appender.append(translateDefaultConstructor(cd)); - - appender.append(SourceEntry.BLOCK_END); - - return appender; - } - - @Override - public Set aggregateDependencies() { - Set ourDependencies = new HashSet(); - - // Add all dependencies from the FieldTranslator - ourDependencies.addAll(fieldTranslator.getDependencies()); - - // Add all dependencies from the MetaInfo translator - ourDependencies.addAll(metaInfoTranslator.getDependencies()); - - return ourDependencies; - } -} +package simpl.translators.java; + + +import java.util.HashSet; +import java.util.Set; + +import ecologylab.appframework.types.prefs.MetaPrefString; +import ecologylab.serialization.ClassDescriptor; + +import simpl.translation.api.ClassTranslator; +import simpl.translation.api.CommentTranslator; +import simpl.translation.api.FieldTranslator; +import simpl.translation.api.MetaInformationTranslator; +import simpl.translation.api.SourceAppender; +import simpl.translation.api.SourceCodeAppender; +import simpl.translation.api.SourceEntry; + +public class JavaClassTranslator extends ClassTranslator{ + + private FieldTranslator fieldTranslator = new JavaFieldTranslator(); + private CommentTranslator commentTranslator = new JavaCommentTranslator(); + private MetaInformationTranslator metaInfoTranslator = new JavaMetaInformationTranslator(); + + public SourceAppender translateDefaultConstructor(ClassDescriptor cd) + { + SourceAppender appender = new SourceCodeAppender(); + appender.append("public " + cd.getDescribedClassSimpleName() + "()"); + appender.append(SourceEntry.BLOCK_BEGIN); + appender.append(SourceEntry.BLOCK_END); + return appender; + } + + @Override + public SourceAppender translateClass(ClassDescriptor cd) { + + SourceAppender appender = new SourceCodeAppender(); + + StringBuilder appendable = new StringBuilder(); + + appender.append(commentTranslator.translateDocComment(cd.getComment())); + + appender.append("public class " + cd.getDescribedClassSimpleName()); + appender.append(SourceEntry.BLOCK_BEGIN); + + appender.append(fieldTranslator.translateFields(cd)); + + appender.append(translateDefaultConstructor(cd)); + + appender.append(SourceEntry.BLOCK_END); + + return appender; + } + + @Override + public Set aggregateDependencies() { + Set ourDependencies = new HashSet(); + + // Add all dependencies from the FieldTranslator + ourDependencies.addAll(fieldTranslator.getDependencies()); + + // Add all dependencies from the MetaInfo translator + ourDependencies.addAll(metaInfoTranslator.getDependencies()); + + return ourDependencies; + } +} diff --git a/simplTranslators/src/simpl/translators/java/JavaCommentTranslator.java b/simplTranslators/src/simpl/translators/java/JavaCommentTranslator.java index b38a1b27..42fa280c 100644 --- a/simplTranslators/src/simpl/translators/java/JavaCommentTranslator.java +++ b/simplTranslators/src/simpl/translators/java/JavaCommentTranslator.java @@ -1,38 +1,38 @@ -package simpl.translators.java; - -import simpl.translation.api.SourceAppender; -import simpl.translation.api.SourceCodeAppender; -import simpl.translation.api.SourceEntry; -import simpl.translation.api.CommentTranslator; - -public class JavaCommentTranslator implements CommentTranslator -{ - @Override - public SourceAppender translateDocComment(String... comments) { - SourceAppender source = new SourceCodeAppender(); - - if(comments != null && comments.length > 0) - { - if(comments[0] != null) - { - // Start of comment block - source.append("/**"); - for(String commentLine : comments) - { - if(commentLine != null) - { - source.append("* " + commentLine); - } - } - source.append("*/"); - return source; - }else{ - return source; - } - } - else - { - return source; - } - } -} +package simpl.translators.java; + +import simpl.translation.api.SourceAppender; +import simpl.translation.api.SourceCodeAppender; +import simpl.translation.api.SourceEntry; +import simpl.translation.api.CommentTranslator; + +public class JavaCommentTranslator implements CommentTranslator +{ + @Override + public SourceAppender translateDocComment(String... comments) { + SourceAppender source = new SourceCodeAppender(); + + if(comments != null && comments.length > 0) + { + if(comments[0] != null) + { + // Start of comment block + source.append("/**"); + for(String commentLine : comments) + { + if(commentLine != null) + { + source.append("* " + commentLine); + } + } + source.append("*/"); + return source; + }else{ + return source; + } + } + else + { + return source; + } + } +} diff --git a/simplTranslators/src/simpl/translators/java/JavaCompilationUnitTranslator.java b/simplTranslators/src/simpl/translators/java/JavaCompilationUnitTranslator.java index e78a15e5..f52367c8 100644 --- a/simplTranslators/src/simpl/translators/java/JavaCompilationUnitTranslator.java +++ b/simplTranslators/src/simpl/translators/java/JavaCompilationUnitTranslator.java @@ -1,39 +1,39 @@ -package simpl.translators.java; - -import ecologylab.serialization.ClassDescriptor; - - -import simpl.translation.api.ClassTranslator; -import simpl.translation.api.DependencyTranslator; -import simpl.translation.api.SourceAppender; -import simpl.translation.api.SourceCodeAppender; -import simpl.translation.api.SourceEntry; - -public class JavaCompilationUnitTranslator{ - - DependencyTranslator dt = new JavaDependencyTranslator(); - ClassTranslator ct = new JavaClassTranslator(); - - public SourceAppender translatePackage(ClassDescriptor cd) - { - SourceAppender sa = new SourceCodeAppender(); - return sa.append("package " + cd.getDescribedClass().getPackage().getName() + ";"); - } - - public String translateClass(ClassDescriptor cd) - { - SourceAppender classRepr = ct.translateClass(cd); - - SourceAppender deps = dt.translateClassDependencies(ct.getDependencies()); - - SourceAppender packageName = translatePackage(cd); - - SourceAppender sa = new SourceCodeAppender(); - sa.append(packageName); - sa.append(SourceEntry.BREAK); - sa.append(deps); - sa.append(classRepr); - - return sa.toSource(); - } -} +package simpl.translators.java; + +import ecologylab.serialization.ClassDescriptor; + + +import simpl.translation.api.ClassTranslator; +import simpl.translation.api.DependencyTranslator; +import simpl.translation.api.SourceAppender; +import simpl.translation.api.SourceCodeAppender; +import simpl.translation.api.SourceEntry; + +public class JavaCompilationUnitTranslator{ + + DependencyTranslator dt = new JavaDependencyTranslator(); + ClassTranslator ct = new JavaClassTranslator(); + + public SourceAppender translatePackage(ClassDescriptor cd) + { + SourceAppender sa = new SourceCodeAppender(); + return sa.append("package " + cd.getDescribedClass().getPackage().getName() + ";"); + } + + public String translateClass(ClassDescriptor cd) + { + SourceAppender classRepr = ct.translateClass(cd); + + SourceAppender deps = dt.translateClassDependencies(ct.getDependencies()); + + SourceAppender packageName = translatePackage(cd); + + SourceAppender sa = new SourceCodeAppender(); + sa.append(packageName); + sa.append(SourceEntry.BREAK); + sa.append(deps); + sa.append(classRepr); + + return sa.toSource(); + } +} diff --git a/simplTranslators/src/simpl/translators/java/JavaDependencyTranslator.java b/simplTranslators/src/simpl/translators/java/JavaDependencyTranslator.java index 7e261cae..203abdba 100644 --- a/simplTranslators/src/simpl/translators/java/JavaDependencyTranslator.java +++ b/simplTranslators/src/simpl/translators/java/JavaDependencyTranslator.java @@ -1,57 +1,57 @@ -package simpl.translators.java; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import simpl.translation.api.DependencyTranslator; -import simpl.translation.api.SourceAppender; -import simpl.translation.api.SourceCodeAppender; - -public class JavaDependencyTranslator implements DependencyTranslator { - /** - * All dependencies that every file should include. - */ - @Override - public List getGlobalDependencies() { - return new ArrayList();///List.class.getName(), Map.class.getName()); - } - - /** - * Translates a dependency for a given class to an import statement - */ - @Override - public SourceAppender translateDependency(String s) { - SourceAppender sa = new SourceCodeAppender(); - - if(shouldExcludeDependency(s)) - { - return sa; - } - - return sa.append("import " + s + ";"); - } - - public boolean shouldExcludeDependency(String s) - { - return s.startsWith("java.lang."); - } - - @Override - public SourceAppender translateClassDependencies(Collection classDependencies) { - - SourceAppender sa = new SourceCodeAppender(); - - for(String dep : getGlobalDependencies()) - { - sa.append(translateDependency(dep)); - } - - for(String dep : classDependencies) - { - sa.append(translateDependency(dep)); - } - - return sa; - } -} +package simpl.translators.java; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import simpl.translation.api.DependencyTranslator; +import simpl.translation.api.SourceAppender; +import simpl.translation.api.SourceCodeAppender; + +public class JavaDependencyTranslator implements DependencyTranslator { + /** + * All dependencies that every file should include. + */ + @Override + public List getGlobalDependencies() { + return new ArrayList();///List.class.getName(), Map.class.getName()); + } + + /** + * Translates a dependency for a given class to an import statement + */ + @Override + public SourceAppender translateDependency(String s) { + SourceAppender sa = new SourceCodeAppender(); + + if(shouldExcludeDependency(s)) + { + return sa; + } + + return sa.append("import " + s + ";"); + } + + public boolean shouldExcludeDependency(String s) + { + return s.startsWith("java.lang."); + } + + @Override + public SourceAppender translateClassDependencies(Collection classDependencies) { + + SourceAppender sa = new SourceCodeAppender(); + + for(String dep : getGlobalDependencies()) + { + sa.append(translateDependency(dep)); + } + + for(String dep : classDependencies) + { + sa.append(translateDependency(dep)); + } + + return sa; + } +} diff --git a/simplTranslators/src/simpl/translators/java/JavaFieldTranslator.java b/simplTranslators/src/simpl/translators/java/JavaFieldTranslator.java index 70183e70..a58a6a4c 100644 --- a/simplTranslators/src/simpl/translators/java/JavaFieldTranslator.java +++ b/simplTranslators/src/simpl/translators/java/JavaFieldTranslator.java @@ -1,154 +1,154 @@ -package simpl.translators.java; - -import java.io.IOException; -import java.util.Set; - -import ecologylab.generic.Debug; -import ecologylab.serialization.ClassDescriptor; -import ecologylab.serialization.FieldDescriptor; -import ecologylab.serialization.MetaInformation; - -import simpl.translation.api.CommentTranslator; -import simpl.translation.api.FieldTranslator; -import simpl.translation.api.LanguageCore; -import simpl.translation.api.MetaInformationTranslator; -import simpl.translation.api.SourceAppender; -import simpl.translation.api.SourceCodeAppender; -import simpl.translation.api.SourceEntry; - -public class JavaFieldTranslator extends FieldTranslator{ - - private final CommentTranslator commentTranslator = new JavaCommentTranslator(); - private final MetaInformationTranslator metaInformationTranslator = new JavaMetaInformationTranslator(); - private final LanguageCore javaCore = new JavaLanguageCore(); - - public JavaFieldTranslator() { - // TODO Auto-generated constructor stub - } - - public SourceAppender translateField(ClassDescriptor context, FieldDescriptor fieldDescriptor) - { - - SourceAppender appender = new SourceCodeAppender(); - - StringBuilder appendable = new StringBuilder(); - - String javaType = fieldDescriptor.getJavaTypeName(); - String simpleJavaTypeName = fieldDescriptor.getFieldTypeSimpleName(); - - addDependency(fieldDescriptor.getJavaTypeName()); - - if (javaType == null) - { - throw new RuntimeException("Invalid type for FieldDescriptor: " + fieldDescriptor.getName()); - } - - boolean isKeyword = checkForKeywords(fieldDescriptor); - if (isKeyword) - return appender; // We didn't make a change to it; so just return an empty appender - - // If it has comments... - if(fieldDescriptor.getComment() != null) - { - SourceAppender comments = commentTranslator.translateDocComment(fieldDescriptor.getComment()); - appender.append(comments); - } - - // if it has metainfo - if(!fieldDescriptor.getMetaInformation().isEmpty()) - { - for(MetaInformation m : fieldDescriptor.getMetaInformation()) - { - appender.append(metaInformationTranslator.translateMetaInformation(m)); - } - } - - - // private simpleJavaTypeName name - appendable.append("private ").append(simpleJavaTypeName).append(" ").append(fieldDescriptor.getName()).append(";"); - - - return appender.append(appendable.toString()).append(SourceEntry.BREAK); - - } - - private String capitalizeFirst(String s) - { - String firstchar = s.substring(0,1); - firstchar = firstchar.toUpperCase(); - - return firstchar + s.substring(1,s.length()); - } - - private SourceAppender translateGetterSetter(ClassDescriptor context, FieldDescriptor fieldDescriptor) - { - SourceAppender appender = new SourceCodeAppender(); - - if(fieldDescriptor.hasGetter()) // By default, always true. - { - String methodTitle = "public " + fieldDescriptor.getFieldTypeSimpleName() + " get" + capitalizeFirst(fieldDescriptor.getName()) +"()"; - appender.append(methodTitle); - appender.append(SourceEntry.BLOCK_BEGIN); - String methodContents = "return this." + fieldDescriptor.getName() + ";"; - appender.append(methodContents); - appender.append(SourceEntry.BLOCK_END); - appender.append(SourceEntry.BREAK); - } - - if(fieldDescriptor.hasSetter()) // By default, always true. - { - String methodTitle = "public void set" + capitalizeFirst(fieldDescriptor.getName()) +"("+fieldDescriptor.getFieldTypeSimpleName() +" value)"; - appender.append(methodTitle); - appender.append(SourceEntry.BLOCK_BEGIN); - String methodContents = "this." + fieldDescriptor.getName() + " = value;"; - appender.append(methodContents); - appender.append(SourceEntry.BLOCK_END); - appender.append(SourceEntry.BREAK); - } - - return appender; - } - - public SourceAppender translateFields(ClassDescriptor context) - { - SourceAppender appender = new SourceCodeAppender(); - - for(Object fd : context.allFieldDescriptors()) - { - appender.append(this.translateField(context, (FieldDescriptor)fd)); - // This ugly cast is here because the API is changing. - // Dont' worry! Translation code you write today will still work soon! - } - - for(Object fd : context.allFieldDescriptors()) - { - appender.append(this.translateGetterSetter(context, (FieldDescriptor)fd)); - } - - return appender; - } - - /** - * A method to test whether fieldAccessor is a java keyword - * - * @param fieldDescriptor - * @return - * @throws IOException - */ - protected boolean checkForKeywords(FieldDescriptor fieldDescriptor) - { - if (javaCore.isKeyword(fieldDescriptor.getName())) - { - Debug.warning(fieldDescriptor, " Field Name: [" + fieldDescriptor.getName() - + "]. This is a keyword in Java. Cannot translate."); - return true; - } - return false; - } - - @Override - public Set aggregateDependencies() { - // TODO Auto-generated method stub - return metaInformationTranslator.getDependencies(); - } -} +package simpl.translators.java; + +import java.io.IOException; +import java.util.Set; + +import ecologylab.generic.Debug; +import ecologylab.serialization.ClassDescriptor; +import ecologylab.serialization.FieldDescriptor; +import ecologylab.serialization.MetaInformation; + +import simpl.translation.api.CommentTranslator; +import simpl.translation.api.FieldTranslator; +import simpl.translation.api.LanguageCore; +import simpl.translation.api.MetaInformationTranslator; +import simpl.translation.api.SourceAppender; +import simpl.translation.api.SourceCodeAppender; +import simpl.translation.api.SourceEntry; + +public class JavaFieldTranslator extends FieldTranslator{ + + private final CommentTranslator commentTranslator = new JavaCommentTranslator(); + private final MetaInformationTranslator metaInformationTranslator = new JavaMetaInformationTranslator(); + private final LanguageCore javaCore = new JavaLanguageCore(); + + public JavaFieldTranslator() { + // TODO Auto-generated constructor stub + } + + public SourceAppender translateField(ClassDescriptor context, FieldDescriptor fieldDescriptor) + { + + SourceAppender appender = new SourceCodeAppender(); + + StringBuilder appendable = new StringBuilder(); + + String javaType = fieldDescriptor.getJavaTypeName(); + String simpleJavaTypeName = fieldDescriptor.getFieldTypeSimpleName(); + + addDependency(fieldDescriptor.getJavaTypeName()); + + if (javaType == null) + { + throw new RuntimeException("Invalid type for FieldDescriptor: " + fieldDescriptor.getName()); + } + + boolean isKeyword = checkForKeywords(fieldDescriptor); + if (isKeyword) + return appender; // We didn't make a change to it; so just return an empty appender + + // If it has comments... + if(fieldDescriptor.getComment() != null) + { + SourceAppender comments = commentTranslator.translateDocComment(fieldDescriptor.getComment()); + appender.append(comments); + } + + // if it has metainfo + if(!fieldDescriptor.getMetaInformation().isEmpty()) + { + for(MetaInformation m : fieldDescriptor.getMetaInformation()) + { + appender.append(metaInformationTranslator.translateMetaInformation(m)); + } + } + + + // private simpleJavaTypeName name + appendable.append("private ").append(simpleJavaTypeName).append(" ").append(fieldDescriptor.getName()).append(";"); + + + return appender.append(appendable.toString()).append(SourceEntry.BREAK); + + } + + private String capitalizeFirst(String s) + { + String firstchar = s.substring(0,1); + firstchar = firstchar.toUpperCase(); + + return firstchar + s.substring(1,s.length()); + } + + private SourceAppender translateGetterSetter(ClassDescriptor context, FieldDescriptor fieldDescriptor) + { + SourceAppender appender = new SourceCodeAppender(); + + if(fieldDescriptor.hasGetter()) // By default, always true. + { + String methodTitle = "public " + fieldDescriptor.getFieldTypeSimpleName() + " get" + capitalizeFirst(fieldDescriptor.getName()) +"()"; + appender.append(methodTitle); + appender.append(SourceEntry.BLOCK_BEGIN); + String methodContents = "return this." + fieldDescriptor.getName() + ";"; + appender.append(methodContents); + appender.append(SourceEntry.BLOCK_END); + appender.append(SourceEntry.BREAK); + } + + if(fieldDescriptor.hasSetter()) // By default, always true. + { + String methodTitle = "public void set" + capitalizeFirst(fieldDescriptor.getName()) +"("+fieldDescriptor.getFieldTypeSimpleName() +" value)"; + appender.append(methodTitle); + appender.append(SourceEntry.BLOCK_BEGIN); + String methodContents = "this." + fieldDescriptor.getName() + " = value;"; + appender.append(methodContents); + appender.append(SourceEntry.BLOCK_END); + appender.append(SourceEntry.BREAK); + } + + return appender; + } + + public SourceAppender translateFields(ClassDescriptor context) + { + SourceAppender appender = new SourceCodeAppender(); + + for(Object fd : context.allFieldDescriptors()) + { + appender.append(this.translateField(context, (FieldDescriptor)fd)); + // This ugly cast is here because the API is changing. + // Dont' worry! Translation code you write today will still work soon! + } + + for(Object fd : context.allFieldDescriptors()) + { + appender.append(this.translateGetterSetter(context, (FieldDescriptor)fd)); + } + + return appender; + } + + /** + * A method to test whether fieldAccessor is a java keyword + * + * @param fieldDescriptor + * @return + * @throws IOException + */ + protected boolean checkForKeywords(FieldDescriptor fieldDescriptor) + { + if (javaCore.isKeyword(fieldDescriptor.getName())) + { + Debug.warning(fieldDescriptor, " Field Name: [" + fieldDescriptor.getName() + + "]. This is a keyword in Java. Cannot translate."); + return true; + } + return false; + } + + @Override + public Set aggregateDependencies() { + // TODO Auto-generated method stub + return metaInformationTranslator.getDependencies(); + } +} diff --git a/simplTranslators/src/simpl/translators/java/JavaLanguageCore.java b/simplTranslators/src/simpl/translators/java/JavaLanguageCore.java index bd588a89..bb668725 100644 --- a/simplTranslators/src/simpl/translators/java/JavaLanguageCore.java +++ b/simplTranslators/src/simpl/translators/java/JavaLanguageCore.java @@ -1,71 +1,71 @@ -package simpl.translators.java; - -import java.util.Map; -import java.util.HashMap; - - -import simpl.translation.api.LanguageCore; - -public class JavaLanguageCore implements LanguageCore{ - - private static Map keywords = new HashMap(); - - static - { - keywords.put("abstract", "abstract"); - keywords.put("continue","continue"); - keywords.put("for","for"); - keywords.put("new","new"); - keywords.put("switch","switch"); - keywords.put("assert","assert"); - keywords.put("default","default"); - keywords.put("package","package"); - keywords.put("synchronized","synchronized"); - keywords.put("boolean","boolean"); - keywords.put("do","do"); - keywords.put("if","if"); - keywords.put("private","private"); - keywords.put("this","this"); - keywords.put("break","break"); - keywords.put("double","double"); - keywords.put("implements","implements"); - keywords.put("protected","protected"); - keywords.put("throw","throw"); - keywords.put("byte","byte"); - keywords.put("else","else"); - keywords.put("import","import"); - keywords.put("public","public"); - keywords.put("throws","throws"); - keywords.put("case","case"); - keywords.put("enum","enum"); - keywords.put("instanceof","instanceof"); - keywords.put("return","return"); - keywords.put("transient","transient"); - keywords.put("catch","catch"); - keywords.put("extends","extends"); - keywords.put("int","int"); - keywords.put("short","short"); - keywords.put("try","try"); - keywords.put("char","char"); - keywords.put("final","final"); - keywords.put("interface","interface"); - keywords.put("static","static"); - keywords.put("void","void"); - keywords.put("class","class"); - keywords.put("finally","finally"); - keywords.put("long","long"); - keywords.put("strictfp","strictfp"); - keywords.put("volatile","volatile"); - keywords.put("const","const"); - keywords.put("float","float"); - keywords.put("native ","native "); - keywords.put("super","super"); - keywords.put("while","while"); - keywords.put("goto","goto"); - } - - public boolean isKeyword(String s) - { - return keywords.containsKey(s); - } -} +package simpl.translators.java; + +import java.util.Map; +import java.util.HashMap; + + +import simpl.translation.api.LanguageCore; + +public class JavaLanguageCore implements LanguageCore{ + + private static Map keywords = new HashMap(); + + static + { + keywords.put("abstract", "abstract"); + keywords.put("continue","continue"); + keywords.put("for","for"); + keywords.put("new","new"); + keywords.put("switch","switch"); + keywords.put("assert","assert"); + keywords.put("default","default"); + keywords.put("package","package"); + keywords.put("synchronized","synchronized"); + keywords.put("boolean","boolean"); + keywords.put("do","do"); + keywords.put("if","if"); + keywords.put("private","private"); + keywords.put("this","this"); + keywords.put("break","break"); + keywords.put("double","double"); + keywords.put("implements","implements"); + keywords.put("protected","protected"); + keywords.put("throw","throw"); + keywords.put("byte","byte"); + keywords.put("else","else"); + keywords.put("import","import"); + keywords.put("public","public"); + keywords.put("throws","throws"); + keywords.put("case","case"); + keywords.put("enum","enum"); + keywords.put("instanceof","instanceof"); + keywords.put("return","return"); + keywords.put("transient","transient"); + keywords.put("catch","catch"); + keywords.put("extends","extends"); + keywords.put("int","int"); + keywords.put("short","short"); + keywords.put("try","try"); + keywords.put("char","char"); + keywords.put("final","final"); + keywords.put("interface","interface"); + keywords.put("static","static"); + keywords.put("void","void"); + keywords.put("class","class"); + keywords.put("finally","finally"); + keywords.put("long","long"); + keywords.put("strictfp","strictfp"); + keywords.put("volatile","volatile"); + keywords.put("const","const"); + keywords.put("float","float"); + keywords.put("native ","native "); + keywords.put("super","super"); + keywords.put("while","while"); + keywords.put("goto","goto"); + } + + public boolean isKeyword(String s) + { + return keywords.containsKey(s); + } +} diff --git a/simplTranslators/src/simpl/translators/java/JavaMetaInformationTranslator.java b/simplTranslators/src/simpl/translators/java/JavaMetaInformationTranslator.java index e5f08a0e..df3fb71a 100644 --- a/simplTranslators/src/simpl/translators/java/JavaMetaInformationTranslator.java +++ b/simplTranslators/src/simpl/translators/java/JavaMetaInformationTranslator.java @@ -1,36 +1,36 @@ -package simpl.translators.java; - -import java.util.Set; - -import ecologylab.serialization.MetaInformation; - -import simpl.translation.api.MetaInformationTranslator; -import simpl.translation.api.SourceAppender; -import simpl.translation.api.SourceCodeAppender; - -public class JavaMetaInformationTranslator extends MetaInformationTranslator{ - JavaParameterTranslator jpt = new JavaParameterTranslator(); - - public SourceAppender translateMetaInformation(MetaInformation metaInfo) { - - SourceAppender appender = new SourceCodeAppender(); - - StringBuilder appendable =new StringBuilder(); - - appendable.append("@").append(metaInfo.simpleTypeName); - if (!metaInfo.getAnnotationParameters().isEmpty()) - { - String parameterList = jpt.translateParameterList(metaInfo.getAnnotationParameters()); - appendable.append(parameterList); - } - - this.addDependency(metaInfo.typeName); - - return appender.append(appendable.toString()); - } - - public Set aggregateDependencies() { - // The parameter translator is our only other class that will have dependencies. - return jpt.getDependencies(); - } +package simpl.translators.java; + +import java.util.Set; + +import ecologylab.serialization.MetaInformation; + +import simpl.translation.api.MetaInformationTranslator; +import simpl.translation.api.SourceAppender; +import simpl.translation.api.SourceCodeAppender; + +public class JavaMetaInformationTranslator extends MetaInformationTranslator{ + JavaParameterTranslator jpt = new JavaParameterTranslator(); + + public SourceAppender translateMetaInformation(MetaInformation metaInfo) { + + SourceAppender appender = new SourceCodeAppender(); + + StringBuilder appendable =new StringBuilder(); + + appendable.append("@").append(metaInfo.simpleTypeName); + if (!metaInfo.getAnnotationParameters().isEmpty()) + { + String parameterList = jpt.translateParameterList(metaInfo.getAnnotationParameters()); + appendable.append(parameterList); + } + + this.addDependency(metaInfo.typeName); + + return appender.append(appendable.toString()); + } + + public Set aggregateDependencies() { + // The parameter translator is our only other class that will have dependencies. + return jpt.getDependencies(); + } } \ No newline at end of file diff --git a/simplTranslators/src/simpl/translators/java/JavaParameterTranslator.java b/simplTranslators/src/simpl/translators/java/JavaParameterTranslator.java index a0c7f289..54e05e6e 100644 --- a/simplTranslators/src/simpl/translators/java/JavaParameterTranslator.java +++ b/simplTranslators/src/simpl/translators/java/JavaParameterTranslator.java @@ -1,100 +1,100 @@ -package simpl.translators.java; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import simpl.descriptors.ParameterDescriptor; -import simpl.translation.api.ParameterTranslator; -import ecologylab.serialization.annotations.Hint; - -public class JavaParameterTranslator extends ParameterTranslator { - - public String translateParameter(ParameterDescriptor d) - { - StringBuilder appendable = new StringBuilder(); - - if(d.isAttributeParameter()) - { - // Get our value - String valueString = translateParameterValue(d.getParameterValue()); - - if(d.getParameterName() != null) - { - appendable.append(d.getParameterName()); - appendable.append("="); - } - - appendable.append(valueString); - } - else if(d.isMethodParameter()) - { - throw new RuntimeException("Invocation / method translation is not implemented yet"); - }else{ - throw new RuntimeException("Invalid ParameterDescriptor at translation time"); - } - - return appendable.toString(); - } - - public String translateParameterValue(Object argValue) - { - if (argValue instanceof String) - { - return "\"" + argValue.toString() + "\""; - } - else if (argValue instanceof Hint) - { - addDependency(Hint.class.getName()); - switch ((Hint) argValue) - { - case XML_ATTRIBUTE: return "Hint.XML_ATTRIBUTE"; - case XML_LEAF: return "Hint.XML_LEAF"; - case XML_LEAF_CDATA: return "Hint.XML_LEAF_CDATA"; - case XML_TEXT: return "Hint.XML_TEXT"; - case XML_TEXT_CDATA: return "Hint.XML_TEXT_CDATA"; - default: return "Hint.UNDEFINED"; - } - } - else if (argValue instanceof Class) - { - addDependency(((Class) argValue).getName()); - return ((Class) argValue).getSimpleName() + ".class"; - }else if (argValue instanceof Number) - { - return argValue.toString(); - } - else{ - throw new RuntimeException("Type of parameter value is currently not supported: " + argValue.getClass().getName() + " To string: " + argValue.getClass().toString()); - } - } - - public String translateParameterList(List parameterList) { - - StringBuilder sb = new StringBuilder(); - sb.append("("); - - int size = parameterList.size(); - for(int i = 0; i < size; i++) - { - ParameterDescriptor pd = parameterList.get(i); - - sb.append(translateParameter(pd)); - - if(i + 1 < size) - { - sb.append(", "); - } - } - - sb.append(")"); - - return sb.toString(); - } - - public Set aggregateDependencies() { - return new HashSet(); // no higher level dependencies. - } - -} +package simpl.translators.java; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import simpl.descriptors.ParameterDescriptor; +import simpl.translation.api.ParameterTranslator; +import ecologylab.serialization.annotations.Hint; + +public class JavaParameterTranslator extends ParameterTranslator { + + public String translateParameter(ParameterDescriptor d) + { + StringBuilder appendable = new StringBuilder(); + + if(d.isAttributeParameter()) + { + // Get our value + String valueString = translateParameterValue(d.getParameterValue()); + + if(d.getParameterName() != null) + { + appendable.append(d.getParameterName()); + appendable.append("="); + } + + appendable.append(valueString); + } + else if(d.isMethodParameter()) + { + throw new RuntimeException("Invocation / method translation is not implemented yet"); + }else{ + throw new RuntimeException("Invalid ParameterDescriptor at translation time"); + } + + return appendable.toString(); + } + + public String translateParameterValue(Object argValue) + { + if (argValue instanceof String) + { + return "\"" + argValue.toString() + "\""; + } + else if (argValue instanceof Hint) + { + addDependency(Hint.class.getName()); + switch ((Hint) argValue) + { + case XML_ATTRIBUTE: return "Hint.XML_ATTRIBUTE"; + case XML_LEAF: return "Hint.XML_LEAF"; + case XML_LEAF_CDATA: return "Hint.XML_LEAF_CDATA"; + case XML_TEXT: return "Hint.XML_TEXT"; + case XML_TEXT_CDATA: return "Hint.XML_TEXT_CDATA"; + default: return "Hint.UNDEFINED"; + } + } + else if (argValue instanceof Class) + { + addDependency(((Class) argValue).getName()); + return ((Class) argValue).getSimpleName() + ".class"; + }else if (argValue instanceof Number) + { + return argValue.toString(); + } + else{ + throw new RuntimeException("Type of parameter value is currently not supported: " + argValue.getClass().getName() + " To string: " + argValue.getClass().toString()); + } + } + + public String translateParameterList(List parameterList) { + + StringBuilder sb = new StringBuilder(); + sb.append("("); + + int size = parameterList.size(); + for(int i = 0; i < size; i++) + { + ParameterDescriptor pd = parameterList.get(i); + + sb.append(translateParameter(pd)); + + if(i + 1 < size) + { + sb.append(", "); + } + } + + sb.append(")"); + + return sb.toString(); + } + + public Set aggregateDependencies() { + return new HashSet(); // no higher level dependencies. + } + +} diff --git a/simplTranslators/test/.gitignore b/simplTranslators/test/.gitignore deleted file mode 100644 index 29b07f2e..00000000 --- a/simplTranslators/test/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -#java specific -*.class - -#netbeans ignore personal stuff -nbproject/private/ - - -## generic files to ignore -*~ -*.lock -*.DS_Store -*.swp -*.out diff --git a/simplTranslators/test/ecologylab/translators/TestCodeTranslatorConfig.java b/simplTranslators/test/ecologylab/translators/TestCodeTranslatorConfig.java new file mode 100644 index 00000000..a0b8363e --- /dev/null +++ b/simplTranslators/test/ecologylab/translators/TestCodeTranslatorConfig.java @@ -0,0 +1,25 @@ +package ecologylab.translators; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Before; +import org.junit.Test; + +public class TestCodeTranslatorConfig +{ + + CodeTranslatorConfig config; + + @Before + public void init() + { + config = new CodeTranslatorConfig(); + } + + @Test + public void testConstruction() + { + assertNotNull(config); + } + +}