/* * Created on Apr 5, 2005 */ package edu.mit.simile.fresnel.configuration; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Vector; import org.openrdf.model.Literal; import org.openrdf.model.Resource; import org.openrdf.model.Statement; import org.openrdf.model.URI; import org.openrdf.model.Value; import org.openrdf.repository.Repository; import org.openrdf.repository.RepositoryConnection; import org.openrdf.repository.RepositoryException; import org.openrdf.repository.RepositoryResult; import fr.inria.jfresnel.fsl.FSLPath; import edu.mit.simile.fresnel.FresnelCoreTypes; import edu.mit.simile.fresnel.FresnelResource; import edu.mit.simile.fresnel.format.Format; import edu.mit.simile.fresnel.format.FormatDescription; import edu.mit.simile.fresnel.format.Style; import edu.mit.simile.fresnel.selection.FSESelector; import edu.mit.simile.fresnel.selection.ISelector; import edu.mit.simile.fresnel.selection.Lens; import edu.mit.simile.fresnel.selection.ParsingException; import edu.mit.simile.fresnel.selection.SPARQLSelector; import edu.mit.simile.fresnel.selection.TypeSelector; import edu.mit.simile.fresnel.selection.UnresolvableException; import edu.mit.simile.fresnel.util.DC; import edu.mit.simile.fresnel.util.RDFList; import edu.mit.simile.vocabularies.FresnelCore; import edu.mit.simile.vocabularies.FresnelExtended; /** * Represents a grouping of lenses and/or styles that will work * consistently with one another. * * @author ryanlee */ public class Group extends FresnelResource { /** * Resource defined in the schema. */ protected final static Resource _schemaResource = FresnelCore.Group; /** * Context for determining FSL first location step type. */ protected final static short _fslContext = FSLPath.NODE_STEP; /** * Resource identifying this group. */ protected Resource _identifier; /** * Name for this group. */ protected String _title; /** * Lenses that act as part of this group. */ private Set<Lens> _lenses; /** * Lenses in this group that act as primaries. */ private Set<ISelector> _primaries; /** * Formats that act as part of this group. */ private Set<Format> _formats; /** * The styling for a resource */ private Set<Style> _resourceStyle; /** * The styling for a property */ private Set<Style> _propertyStyle; /** * The styling for a label */ private Set<Style> _labelStyle; /** * The styling for a value */ private Set<Style> _valueStyle; /** * The formatting for a resource */ private Set<FormatDescription> _resourceFormat; /** * The formatting for a property */ private Set<FormatDescription> _propertyFormat; /** * The formatting for a label */ private Set<FormatDescription> _labelFormat; /** * The formatting for a value */ private Set<FormatDescription> _valueFormat; /** * Links to a CSS stylesheet in a vector form. */ private Vector<String> _cssLinks; /** * Empty constructor. */ public Group() { this._lenses = new HashSet<Lens>(); this._formats = new HashSet<Format>(); this._primaries = new HashSet<ISelector>(); this._resourceStyle = new HashSet<Style>(); this._propertyStyle = new HashSet<Style>(); this._labelStyle = new HashSet<Style>(); this._valueStyle = new HashSet<Style>(); this._resourceFormat = new HashSet<FormatDescription>(); this._propertyFormat = new HashSet<FormatDescription>(); this._labelFormat = new HashSet<FormatDescription>(); this._valueFormat = new HashSet<FormatDescription>(); this._cssLinks = new Vector<String>(); } /** * Constructs a group with a <code>Resource</code> identifier. * * @param id A <code>Resource</code> that is a group. */ public Group(Resource id) { this(); this._identifier = id; } /** * Retrieves the identifier of the group. * * @return A <code>Resource</code> */ public Resource getIdentifier() { return this._identifier; } /** * Retrieves a set of lenses associated with a group. * * @return A <code>LensSet</code> of coordinated lenses. */ public Set<Lens> getLenses() { return this._lenses; } /** * Retreives the set of primary classes associated with a group. * * @return A <code>DomainSet</code> of resources considered primary. */ public Set<ISelector> getPrimaries() { return this._primaries; } /** * Retrieves a set of formats associated with a group. * * @return A <code>FormatSet</code> of coordinated formats. */ public Set<Format> getFormats() { return this._formats; } /** * Retreives the set of default resource styles, applied to all group resources * * @return A <code>StyleSet</code> */ public Set<Style> getResourceStyle() { return this._resourceStyle; } /** * Retreives the set of default property styles, applied to all group properties * * @return A <code>StyleSet</code> */ public Set<Style> getPropertyStyle() { return this._propertyStyle; } /** * Retreives the set of default label styles, applied to all group properties * * @return A <code>StyleSet</code> */ public Set<Style> getLabelStyle() { return this._labelStyle; } /** * Retreives the set of default value styles, applied to all group properties * * @return A <code>StyleSet</code> */ public Set<Style> getValueStyle() { return this._valueStyle; } /** * Retrieves the format values associated with resources * * @return A <code>FormatDescriptionSet</code> */ public Set<FormatDescription> getResourceFormat() { return this._resourceFormat; } /** * Retrieves the format values associated with properties * * @return A <code>FormatDescriptionSet</code> */ public Set<FormatDescription> getPropertyFormat() { return this._propertyFormat; } /** * Retrieves the format values associated with labels * * @return A <code>FormatDescriptionSet</code> */ public Set<FormatDescription> getLabelFormat() { return this._labelFormat; } /** * Retrieves the format values associated with values * * @return A <code>FormatDescriptionSet</code> */ public Set<FormatDescription> getValueFormat() { return this._valueFormat; } /** * Returns the provided links to CSS stylesheets * * @return A <code>Vector</code> of <code>String</code>s */ public Vector<String> getCssLinks() { return this._cssLinks; } /** * Retrieves whether this group has primary classes associated with it. * * @return True if more than one primary class is set, false if not. */ public boolean hasPrimaries() { return (this._primaries.size() > 0); } /** * Retrieves whether this group has any CSS stylesheets associated with it. * * @return True if any stylesheet links are given, false if not. */ public boolean hasCssLinks() { return (this._cssLinks.size() > 0); } /** * Returns the name of the group. * * @return The <code>String</code> name */ public String getTitle() { String title = this._title; if (null == title) { if (getIdentifier() instanceof URI) title = ((URI) getIdentifier()).getLocalName(); else title = "[untitled group]"; } return title; } /** * Sets the name for the group. * * @param title A <code>String</code> */ public void setTitle(String title) { this._title = title; } /** * Sets the bundle of lenses for a group. * * @param set A <code>LensSet</code> */ public void setLenses(Set<Lens> set) { this._lenses = set; } /** * Adds another lens to the existing bundle of lenses. * * @param lens A <code>Lens</code> */ public void addLens(Lens lens) { this._lenses.add(lens); } /** * Removes a lens from the existing bundle of lenses. * * @param lens A <code>Lens</code> */ public void removeLens(Lens lens) { this._lenses.remove(lens); } /** * Sets the bundle of formats for this group. * * @param set A <code>FormatSet</code> */ public void setFormats(Set<Format> set) { this._formats = set; } /** * Adds a format to the existing style bundle. * * @param format A <code>Format</code> */ public void addFormat(Format format) { this._formats.add(format); } /** * Removes a format from the existing style bundle. * * @param format A <code>Format</code> */ public void removeFormat(Format format) { this._formats.remove(format); } /** * Sets the primary classes for the group. * * @param primaries A <code>DomainSet</code> of all primary classes for the group. */ public void setPrimaries(Set<ISelector> primaries) { this._primaries = primaries; } /** * Adds another primary to the existing set of primaries. * * @param primary An <code>ISelector</code> */ public void addPrimary(ISelector primary) { this._primaries.add(primary); } /** * Removes a primary from the existing set of primaries. * * @param primary An existing <code>ISelector</code> */ public void removePrimary(ISelector primary) { this._primaries.remove(primary); } /** * Sets the styling for resources * * @param style A <code>StyleSet</code> */ protected void setResourceStyle(Set<Style> style) { this._resourceStyle = style; } /** * Sets the styling for properties * * @param style A <code>StyleSet</code> */ protected void setPropertyStyle(Set<Style> style) { this._propertyStyle = style; } /** * Sets the styling for labels * * @param style A <code>StyleSet</code> */ protected void setLabelStyle(Set<Style> style) { this._labelStyle = style; } /** * Sets the styling for values * * @param style A <code>StyleSet</code> */ protected void setValueStyle(Set<Style> style) { this._valueStyle = style; } /** * Adds a styling for resources * * @param style A <code>Style</code> */ protected void addResourceStyle(Style style) { this._resourceStyle.add(style); } /** * Adds a styling for properties * * @param style A <code>Style</code> */ protected void addPropertyStyle(Style style) { this._propertyStyle.add(style); } /** * Adds a styling for labels * * @param style A <code>Style</code> */ protected void addLabelStyle(Style style) { this._labelStyle.add(style); } /** * Adds a styling for values * * @param style A <code>Style</code> */ protected void addValueStyle(Style style) { this._valueStyle.add(style); } /** * Sets the formatting for resources * * @param fd A <code>FormatDescriptionSet</code> */ protected void setResourceFormat(Set<FormatDescription> fd) { this._resourceFormat = fd; } /** * Sets the formatting for properties * * @param fd A <code>FormatDescriptionSet</code> */ protected void setPropertyFormat(Set<FormatDescription> fd) { this._propertyFormat = fd; } /** * Sets the formatting for labels * * @param fd A <code>FormatDescriptionSet</code> */ protected void setLabelFormat(Set<FormatDescription> fd) { this._labelFormat = fd; } /** * Sets the formatting for values * * @param fd A <code>FormatDescriptionSet</code> */ protected void setValueFormat(Set<FormatDescription> fd) { this._valueFormat = fd; } /** * Adds a formatting for resources * * @param format A <code>FormatDescription</code> */ protected void addResourceFormat(FormatDescription format) { this._resourceFormat.add(format); } /** * Adds a formatting for properties * * @param format A <code>FormatDescription</code> */ protected void addPropertyFormat(FormatDescription format) { this._propertyFormat.add(format); } /** * Adds a formatting for labels * * @param format A <code>FormatDescription</code> */ protected void addLabelFormat(FormatDescription format) { this._labelFormat.add(format); } /** * Adds a formatting for values * * @param format A <code>FormatDescription</code> */ protected void addValueFormat(FormatDescription format) { this._valueFormat.add(format); } /** * Adds a CSS stylesheet link. * * @param link A <code>String</code> URL */ protected void addCssLink(String link) { this._cssLinks.add(link); } /** * Parses a model based on the resource into a group object. * * @param in The source <code>Repository</code> * @param selected The identifying <code>Resource</code> * @param conf The base <code>Configuration</code> * @return A new <code>Group</code> * @throws UnresolvableException If too many values are found for a property where only a certain number are allowed * @throws ParsingException If semantic errors are found in the group configuration */ public static Group parse(Repository in, Resource selected, Configuration conf) throws UnresolvableException, ParsingException { Group out = new Group(selected); try { RepositoryConnection conn = in.getConnection(); // name for the group RepositoryResult<Statement> titleI = conn.getStatements(selected, DC.title, (Value) null, false); while (titleI.hasNext()) { Statement titleS = titleI.next(); Literal titleObj = (Literal) titleS.getObject(); out.setTitle(titleObj.getLabel()); } titleI.close(); // resource style RepositoryResult<Statement> resourceStyleI = conn.getStatements(selected, FresnelCore.resourceStyle, (Value) null, false); while (resourceStyleI.hasNext()) { Statement resourceStyleS = resourceStyleI.next(); Value styleObj = resourceStyleS.getObject(); out.addResourceStyle(Style.parse(styleObj)); } resourceStyleI.close(); // property style RepositoryResult<Statement> propertyStyleI = conn.getStatements(selected, FresnelCore.propertyStyle, (Value) null, false); while (propertyStyleI.hasNext()) { Statement propertyStyleS = propertyStyleI.next(); Value styleObj = propertyStyleS.getObject(); out.addPropertyStyle(Style.parse(styleObj)); } propertyStyleI.close(); // label style RepositoryResult<Statement> labelStyleI = conn.getStatements(selected, FresnelCore.labelStyle, (Value) null, false); while (labelStyleI.hasNext()) { Statement labelStyleS = labelStyleI.next(); Value styleObj = labelStyleS.getObject(); out.addLabelStyle(Style.parse(styleObj)); } labelStyleI.close(); // value style RepositoryResult<Statement> valueStyleI = conn.getStatements(selected, FresnelCore.valueStyle, (Value) null, false); while (valueStyleI.hasNext()) { Statement valueStyleS = valueStyleI.next(); Value styleObj = valueStyleS.getObject(); out.addValueStyle(Style.parse(styleObj)); } valueStyleI.close(); // resource format RepositoryResult<Statement> resourceFormatI = conn.getStatements(selected, FresnelCore.resourceFormat, (Value) null, false); while (resourceFormatI.hasNext()) { Statement resourceFormatS = resourceFormatI.next(); Resource formatObj = (Resource) resourceFormatS.getObject(); out.addResourceFormat(FormatDescription.parse(in, formatObj)); } resourceFormatI.close(); // property format RepositoryResult<Statement> propertyFormatI = conn.getStatements(selected, FresnelCore.propertyFormat, (Value) null, false); while (propertyFormatI.hasNext()) { Statement propertyFormatS = propertyFormatI.next(); Resource formatObj = (Resource) propertyFormatS.getObject(); out.addPropertyFormat(FormatDescription.parse(in, formatObj)); } propertyFormatI.close(); // label format RepositoryResult<Statement> labelFormatI = conn.getStatements(selected, FresnelCore.labelFormat, (Value) null, false); while (labelFormatI.hasNext()) { Statement labelFormatS = labelFormatI.next(); Resource formatObj = (Resource) labelFormatS.getObject(); out.addLabelFormat(FormatDescription.parse(in, formatObj)); } labelFormatI.close(); // value format RepositoryResult<Statement> valueFormatI = conn.getStatements(selected, FresnelCore.valueFormat, (Value) null, false); while (valueFormatI.hasNext()) { Statement valueFormatS = valueFormatI.next(); Resource formatObj = valueFormatS.getSubject(); out.addValueFormat(FormatDescription.parse(in, formatObj)); } valueFormatI.close(); // EXTENDED: stylesheet link RepositoryResult<Statement> cssLinkI = conn.getStatements(selected, FresnelExtended.stylesheetLink, (Value) null, false); while (cssLinkI.hasNext()) { Statement cssLinkS = cssLinkI.next(); Value linkObj = cssLinkS.getObject(); if (linkObj instanceof Literal) out.addCssLink(((Literal) linkObj).getLabel()); else out.addCssLink(((URI) linkObj).toString()); } cssLinkI.close(); RepositoryResult<Statement> groupPrimaries = conn.getStatements(selected, FresnelCore.primaryClasses, (Value) null, false); if (groupPrimaries.hasNext()) { Statement primaryStmt = groupPrimaries.next(); if (groupPrimaries.hasNext()) throw new UnresolvableException("Too many fresnel:primaryClass predicates used, only one expected."); Value primaryObj = primaryStmt.getObject(); if (primaryObj instanceof Resource && RDFList.isRDFList(in, (Resource) primaryObj)) { List primaries = new RDFList(in, (Resource) primaryObj).asJavaList(); Iterator primaryDomains = primaries.iterator(); while (primaryDomains.hasNext()) { Value domainNode = (Value) primaryDomains.next(); ISelector domain = null; if (domainNode instanceof Resource) { // This is a type selector domain = new TypeSelector((Resource) domainNode); } else if (domainNode instanceof Literal) { Literal domainL = (Literal) domainNode; // TODO: catch bad expressions? throw exceptions? if (domainL.getDatatype().equals(FresnelCoreTypes.fslSelector)) { domain = new FSESelector(domainL.getLabel(), _fslContext, conf.getNamespaceMap()); } else if (domainL.getDatatype().equals(FresnelCoreTypes.sparqlSelector)) { domain = new SPARQLSelector(domainL.getLabel(), conf.getNamespaces()); } } else { throw new ParsingException("Could not read member fresnel:primaryClass rdf:List."); } out.addPrimary(domain); } } else { throw new ParsingException("Could not read object of fresnel:primaryClass predicate, expecting an rdf:List."); } } groupPrimaries.close(); conn.close(); } catch (RepositoryException e) { throw new UnresolvableException("Problem connecting to repository: " + e.getLocalizedMessage()); } return out; } /** * @see java.lang.Object#toString() */ public String toString() { String state = " [Group " + super.toString() + "]\n"; state += " " + this._identifier + "\n"; state += this._primaries; state += " " + this._lenses; state += this._formats; if (0 != this._resourceStyle.size()) state += this._resourceStyle + " [resource]\n"; if (0 != this._propertyStyle.size()) state += this._propertyStyle + " [property]\n"; if (0 != this._labelStyle.size()) state += this._labelStyle + " [label]\n"; if (0 != this._valueStyle.size()) state += this._valueStyle + " [value]\n"; state += "\n Content format(s):\n"; if (0 != this._resourceFormat.size()) state += this._resourceFormat + " [resource]\n"; if (0 != this._propertyFormat.size()) state += this._propertyFormat + " [property]\n"; if (0 != this._labelFormat.size()) state += this._labelFormat + " [label]\n"; if (0 != this._valueFormat.size()) state += this._valueFormat + " [value]\n"; state += " ====== [end group]"; return state; } }