package org.splat.simer;
+
/**
*
* @author Daniel Brunier-Coulin
import java.util.List;
import java.util.ResourceBundle;
-import org.splat.manox.XMLDocument;
import org.splat.dal.bo.kernel.Relation;
import org.splat.dal.bo.som.ConvertsRelation;
import org.splat.dal.bo.som.Document;
-import org.splat.som.DocumentRights;
import org.splat.dal.bo.som.DocumentType;
import org.splat.dal.bo.som.ProgressState;
-import org.splat.service.PublicationService;
-import org.splat.service.technical.ProjectSettingsService;
import org.splat.dal.bo.som.Publication;
-import org.splat.som.Revision;
-import org.splat.som.Step;
import org.splat.dal.bo.som.Timestamp;
import org.splat.dal.bo.som.UsesRelation;
import org.splat.dal.bo.som.VersionsRelation;
+import org.splat.manox.XMLDocument;
+import org.splat.service.PublicationService;
+import org.splat.service.technical.ProjectSettingsService;
+import org.splat.som.DocumentRights;
+import org.splat.som.Revision;
+import org.splat.som.Step;
import org.splat.wapp.PopupMenu;
-
+/**
+ * Document wrapper class for presentation layer.
+ */
public class DocumentFacade implements HistoryFacade {
- private OpenObject owner;
- private Publication me;
- private Document my; // Published document
- private ProgressState state; // Document state
- private String version; // My document version in customized format
- private State display; // Presentation state
- private String surl; // URL of the source file
- private String format; // Extension of the source file
- private String icon; // Corresponding icon
- private String sharing; // Icon qualifying sharing between scenarios of a same study
- private String updated; // Icon qualifying versioning from the previous study version
- private String size;
- private String date;
- private String description;
- private List<DocumentFacade> uses;
- private List<FileFacade> exports;
- private List<HistoryFacade> history;
- private PopupMenu popup;
- private ProjectSettingsService _projectSettingsService;
+ /**
+ * Icon extension.
+ */
+ static private final String ICON_EXT = ".png";
+ /**
+ * Document's owner.
+ */
+ private final transient AbstractOpenObject _owner;
+ /**
+ * Wrapped document publication.
+ */
+ private final transient Publication _me;
+ /**
+ * Published document.
+ */
+ private final transient Document _my;
+ /**
+ * Document state.
+ */
+ private transient ProgressState _state;
+ /**
+ * My document version in customized format.
+ */
+ private transient String _version;
+ /**
+ * Presentation state.
+ */
+ private transient State _display;
+ /**
+ * URL of the source file.
+ */
+ private transient String _surl;
+ /**
+ * Corresponding icon.
+ */
+ private transient String _icon;
+ /**
+ * Icon qualifying sharing between scenarios of a same study.
+ */
+ private transient String _sharing;
+ /**
+ * Icon qualifying versioning from the previous study version.
+ */
+ private transient String _updated;
+ /**
+ * Document size.
+ */
+ private transient String _size;
+ /**
+ * Document last modification date.
+ */
+ private transient String _date;
+ /**
+ * Document's description.
+ */
+ private transient String _description;
+ /**
+ * List of used documents presentations.
+ */
+ private transient List<DocumentFacade> _uses;
+ /**
+ * List of attached files presentations.
+ */
+ private transient List<FileFacade> _exports;
+ /**
+ * List of the document's history nodes.
+ */
+ private transient List<HistoryFacade> _history;
+ /**
+ * Document's popup menu.
+ */
+ private transient PopupMenu _popup;
+ /**
+ * Injected project settings service.
+ */
+ private ProjectSettingsService _projectSettings;
+ /**
+ * Injected publication service.
+ */
private PublicationService _publicationService;
-
- private enum State { closed, open, deepopen }
-
-// ==============================================================================================================================
-// Constructors
-// ==============================================================================================================================
-
- public DocumentFacade (OpenObject opened, Publication represented) {
-// ------------------------------------------------------------------
- owner = opened;
- me = represented;
- my = me.value();
- state = my.getProgressState();
- display = State.closed;
- description = null;
- uses = null;
- exports = null;
- history = null;
- popup = null;
-
- this.refresh(); // Initializes the presentation of my document
- }
-/**
- * Constructs the facade of a document presented in the history folder.
- *
- * @param represented the represented history document
- */
- private DocumentFacade (OpenObject opened, Document represented) {
-// ----------------------------------------------------------------
- owner = opened;
- me = null; // Marks the history context
- my = represented;
- state = my.getProgressState(); // In reality, HISTORY
- display = State.open; // Because the given document is a history document
- description = ResourceBundle.getBundle("som", ApplicationSettings.getCurrentLocale()).getString("history.creation") + " " + my.getAuthor().toString();
- uses = null;
- exports = null;
- history = null;
- popup = null;
-
- this.refresh(); // Initializes the presentation of my document
- }
-
-// ==============================================================================================================================
-// Public member functions
-// ==============================================================================================================================
-
- public void develop () {
-// -------------------
- if (display != State.open) { // Opening the document
- if (uses == null) {
- List<Publication> relist = me.getRelations(UsesRelation.class);
-
- uses = new ArrayList<DocumentFacade>(relist.size());
- for (Iterator<Publication> i=relist.iterator(); i.hasNext();) {
- Publication used = i.next();
- Integer index = used.getIndex();
- DocumentFacade facade = OpenObject.docpres.get(index);
- if (facade == null) {
- facade = new DocumentFacade(owner, used);
- OpenObject.docpres.put(index, facade);
- }
- uses.add(facade);
- }
- }
- if (exports == null) {
- List<Relation> relation = my.getRelations(ConvertsRelation.class);
-
- exports = new ArrayList<FileFacade>(relation.size());
- for (Iterator<Relation> i=relation.iterator(); i.hasNext();) {
- ConvertsRelation export = (ConvertsRelation)i.next();
- exports.add( new FileFacade(export) );
- }
- }
- if (history == null) {
- if (my.getPreviousVersion() != null || state == ProgressState.inCHECK || state == ProgressState.APPROVED) history = new ArrayList<HistoryFacade>();
- }
- display = State.open;
- } else { // Opening the history of document, if exist
- if (history.isEmpty()) collectHistory(my);
- display = State.deepopen;
- }
- }
-
- public void reduce () {
-// ---------------------
- if (display == State.deepopen) display = State.open;
- }
-
- public void reduceAll () {
-// ------------------------
- display = State.closed;
- }
-
-// ==============================================================================================================================
-// Getters
-// ==============================================================================================================================
-
- public List<FileFacade> getAttachments () {
-// ------------------------------------------
- return exports;
- }
- public String getDate () {
-// ------------------------
- return date;
- }
- public String getDescription () {
-// -------------------------------
- return description;
- }
- public String getEditIcon () {
-// ----------------------------
- return "icon.ed" + state + ".png";
- }
- public String getFileIcon () {
-// ----------------------------
- return icon;
- }
- public List<HistoryFacade> getHistory () {
-// ----------------------------------------
- return history;
- }
- public String getIndex () {
-// -------------------------
- return String.valueOf(my.getIndex());
- }
- public PopupMenu getPopup () { // Contextualizes the pop-up
-// ----------------------------
- popup.setContext("document", new DocumentRights(owner.getUser(), me));
- return popup; // callers must "use" the returned pop-up before getting another pop-up
- }
- public String getPresentationState () {
-// -------------------------------------
- return display.toString();
- }
- public String getProgressState () {
-// ---------------------------------
- return state.toString();
- }
- public String getSharingIcon () {
-// -------------------------------
- return sharing;
- }
- public String getSize () {
-// ------------------------
- return size;
- }
- public String getStateIcon () {
-// -----------------------------
- return "icon." + state + ".png";
- }
- public String getTitle () {
-// -------------------------
- return my.getTitle();
- }
- public String getURL () {
-// -----------------------
- return surl;
- }
- public List<DocumentFacade> getUses () {
-// ---------------------------------------
- return uses;
- }
- public String getVersion () {
-// ---------------------------
- return version;
- }
- public String getVersioningIcon () {
-// ----------------------------------
- return updated;
- }
- public boolean isFacadeOf (Publication represented) {
-// ---------------------------------------------------
- return me.equals(represented);
- }
-// ==============================================================================================================================
-// Protected services
-// ==============================================================================================================================
-
- protected void refresh () {
-// -------------------------
- ResourceBundle custom = ResourceBundle.getBundle("som", ApplicationSettings.getCurrentLocale());
- DecimalFormat sizstring = new DecimalFormat(custom.getString("size.format")); // Locale size display format
- SimpleDateFormat datstring = new SimpleDateFormat(custom.getString("date.format")); // Locale date display format
- Revision.Format verstring = new Revision.Format(getProjectSettings().getRevisionPattern());
- String path = my.getSourceFile().getRelativePath();
- String[] mapping = ApplicationSettings.getViewersMapping();
-
- for (int i=0; i<mapping.length; i++) {
- org.splat.dal.bo.som.File export = my.getAttachedFile(mapping[i]);
- if (export == null) continue;
- path = export.getRelativePath();
- break;
- }
- surl = ApplicationSettings.getRepositoryURL() + path;
- surl = surl.replaceAll("'", "\\\\'");
- format = my.getFormat();
- if (format.equals("xml")) format = XMLDocument.getActualFormat(my.getSourceFile().asFile());
-
-// Document state (overridable by the publication - see below)
- state = my.getProgressState();
- version = my.getVersion(); // May be null
-
-// Icons definition
- icon = "icon." + format + ".png";
- sharing = "image.hold.gif";
- updated = "image.hold.gif";
- File image = new File(ApplicationSettings.getApplicationSkinPath() + icon);
- if (!image.exists()) icon = "icon.any.png";
-
- if (me != null) {
- if (me.getOwnerStudy().shares(my)) {
- sharing = "image.share.png";
- updated = "icon.hold.png";
- }
- if (me.isOutdated()) state = ProgressState.inWORK; // Overrides the document state
-
- } else { // Facade in the history folder
- if (!my.isVersioned()) { // History of the last version
- if (state != ProgressState.inWORK) icon = "icon.inWORK.png";
- else icon = "icon." + state.toString() + ".png";
- } else
- if ( my.isPublished()) {
- sharing = "image.share.png"; // Not correct if published in a previous version of the study
- updated = "icon.hold.png";
- }
- }
-// Document description
- VersionsRelation versions = (VersionsRelation)my.getFirstRelation(VersionsRelation.class);
- if (versions != null) {
- description = versions.getDescription();
- }
-// File details
- if (state != ProgressState.EXTERN) version = verstring.format(version);
- size = sizstring.format(my.getSourceFile().asFile().length()/1000);
- date = datstring.format(my.getLastModificationDate());
-
-// Refresh of the history in case of promotion
- if (display == State.deepopen) {
- history.clear();
- collectHistory(my);
- }
-// Popup menus
- if (me == null) return; // No pop-up (yet) in the history folder
- if (state == ProgressState.EXTERN) popup = ApplicationSettings.getPopupMenu("extern");
- else if (state == ProgressState.inWORK) popup = ApplicationSettings.getPopupMenu("editable");
- else if (state == ProgressState.inDRAFT) popup = ApplicationSettings.getPopupMenu("reviewable");
- else if (state == ProgressState.APPROVED) popup = ApplicationSettings.getPopupMenu("approved");
- else { //(state == ProgressState.inCHECK)
- DocumentType mytype = me.value().getType(); // Only result documents need to be approved
- Step mystep = getPublicationService().getInvolvedStep(me);
- if (mytype.isResultOf(mystep.getStep())) popup = ApplicationSettings.getPopupMenu("approvable");
- else popup = ApplicationSettings.getPopupMenu("notresult");
- }
- }
-
- protected void setVersioned () {
-// ------------------------------
- updated = "image.modified.png";
- }
-
-// ==============================================================================================================================
-// Private services
-// ==============================================================================================================================
-
- private void collectHistory (Document given) {
-// --------------------------------------------
- VersionsRelation versions = (VersionsRelation)given.getFirstRelation(VersionsRelation.class);
- Timestamp[] stamp = given.getStamps(); // Stamps in ascending order of date
-
- for (int i=stamp.length-1; i>-1; i--) history.add( new StampFacade(stamp[i]) );
- history.add( new DocumentFacade(owner, given) );
- if (versions != null) collectHistory(versions.getTo());
- }
-
- /**
- * Get project settings.
+ /**
+ * Injected application settings.
+ */
+ private ApplicationSettings _applicationSettings;
+
+ /**
+ * Document presentation state enumeration.
+ */
+ private enum State {
+ /**
+ * Closed presentation state.
+ */
+ closed,
+ /**
+ * Open presentation state (history and attached files nodes are visible).
+ */
+ open,
+ /**
+ * Deeply open presentation.
+ */
+ deepopen
+ }
+
+ // ==============================================================================================================================
+ // Constructors
+ // ==============================================================================================================================
+
+ /**
+ * Constructor.
+ *
+ * @param opened
+ * document owner
+ * @param represented
+ * document presentation
+ * @param projectSettings
+ * project settings service
+ * @param publicationService
+ * publication service
+ * @param applicationSettings
+ * application settings
+ */
+ public DocumentFacade(final AbstractOpenObject opened,
+ final Publication represented,
+ final ProjectSettingsService projectSettings,
+ final PublicationService publicationService,
+ final ApplicationSettings applicationSettings) {
+ setProjectSettings(projectSettings);
+ setPublicationService(publicationService);
+ setApplicationSettings(applicationSettings);
+ _owner = opened;
+ _me = represented;
+ _my = _me.value();
+ _state = _my.getProgressState();
+ _display = State.closed;
+
+ refresh(); // Initializes the presentation of my document //NOPMD:RKV: to be reviewed
+ }
+
+ /**
+ * Constructs the facade of a document presented in the history folder.
+ *
+ * @param opened
+ * document owner
+ * @param represented
+ * document presentation
+ * @param projectSettings
+ * project settings service
+ * @param publicationService
+ * publication service
+ * @param applicationSettings
+ * application settings
+ */
+ private DocumentFacade(final AbstractOpenObject opened,
+ final Document represented,
+ final ProjectSettingsService projectSettings,
+ final PublicationService publicationService,
+ final ApplicationSettings applicationSettings) {
+ setProjectSettings(projectSettings);
+ setPublicationService(publicationService);
+ setApplicationSettings(applicationSettings);
+ _owner = opened;
+ _me = null; // Marks the history context
+ _my = represented;
+ _state = _my.getProgressState(); // In reality, HISTORY
+ _display = State.open; // Because the given document is a history document
+ _description = ResourceBundle.getBundle("som",
+ applicationSettings.getCurrentLocale()).getString(
+ "history.creation")
+ + " " + _my.getAuthor().toString();
+ _uses = null;
+ _exports = null;
+ _history = null;
+ _popup = null;
+
+ this.refresh(); // Initializes the presentation of my document
+ }
+
+ // ==============================================================================================================================
+ // Public member functions
+ // ==============================================================================================================================
+
+ /**
+ * Open the presentation subtree.
+ */
+ public void develop() {
+ if (_display == State.open) { // Opening the history of document, if exist
+ if (_history.isEmpty()) {
+ collectHistory(_my);
+ }
+ _display = State.deepopen;
+ } else { // Opening the document
+ if (_uses == null) {
+ List<Publication> relist = _me.getRelations(UsesRelation.class);
+
+ _uses = new ArrayList<DocumentFacade>(relist.size());
+ for (Iterator<Publication> i = relist.iterator(); i.hasNext();) {
+ Publication used = i.next();
+ long index = used.getIndex();
+ DocumentFacade facade = _owner._docpres.get(index);
+ if (facade == null) {
+ facade = new DocumentFacade(_owner, used,
+ getProjectSettings(), getPublicationService(),
+ getApplicationSettings());
+ _owner._docpres.put(index, facade);
+ }
+ _uses.add(facade);
+ }
+ }
+ if (_exports == null) {
+ List<Relation> relation = _my
+ .getRelations(ConvertsRelation.class);
+
+ _exports = new ArrayList<FileFacade>(relation.size());
+ for (Iterator<Relation> i = relation.iterator(); i.hasNext();) {
+ ConvertsRelation export = (ConvertsRelation) i.next();
+ _exports.add(new FileFacade(export,
+ getApplicationSettings()));
+ }
+ }
+ if (_history == null) {
+ if (_my.getPreviousVersion() != null
+ || _state == ProgressState.inCHECK
+ || _state == ProgressState.APPROVED) {
+ _history = new ArrayList<HistoryFacade>();
+ }
+ }
+ _display = State.open;
+ }
+ }
+
+ public void reduce() {
+ if (_display == State.deepopen) {
+ _display = State.open;
+ }
+ }
+
+ public void reduceAll() {
+ _display = State.closed;
+ }
+
+ // ==============================================================================================================================
+ // Getters
+ // ==============================================================================================================================
+
+ public List<FileFacade> getAttachments() {
+ return _exports;
+ }
+
+ public String getDate() {
+ return _date;
+ }
+
+ public String getDescription() {
+ return _description;
+ }
+
+ public String getEditIcon() {
+ return "icon.ed" + _state + ICON_EXT;
+ }
+
+ public String getFileIcon() {
+ return _icon;
+ }
+
+ public List<HistoryFacade> getHistory() {
+ return _history;
+ }
+
+ public String getIndex() {
+ return String.valueOf(_my.getIndex());
+ }
+
+ public PopupMenu getPopup() { // Contextualizes the pop-up
+ _popup
+ .setContext("document", new DocumentRights(_owner.getUser(),
+ _me));
+ return _popup; // callers must "use" the returned pop-up before getting another pop-up
+ }
+
+ public String getPresentationState() {
+ return _display.toString();
+ }
+
+ public String getProgressState() {
+ return _state.toString();
+ }
+
+ public String getSharingIcon() {
+ return _sharing;
+ }
+
+ public String getSize() {
+ return _size;
+ }
+
+ public String getStateIcon() {
+ return "icon." + _state + ICON_EXT;
+ }
+
+ public String getTitle() {
+ return _my.getTitle();
+ }
+
+ public String getURL() {
+ return _surl;
+ }
+
+ public List<DocumentFacade> getUses() {
+ return _uses;
+ }
+
+ public String getVersion() {
+ return _version;
+ }
+
+ public String getVersioningIcon() {
+ return _updated;
+ }
+
+ public boolean isFacadeOf(final Publication represented) {
+ return _me.equals(represented);
+ }
+
+ // ==============================================================================================================================
+ // Protected services
+ // ==============================================================================================================================
+
+ /**
+ * Refresh the document presentation.
+ */
+ protected final void refresh() {
+ ResourceBundle custom = ResourceBundle.getBundle("som",
+ getApplicationSettings().getCurrentLocale());
+ DecimalFormat sizstring = new DecimalFormat(custom
+ .getString("size.format")); // Locale size display format
+ SimpleDateFormat datstring = new SimpleDateFormat(custom
+ .getString("date.format"), getApplicationSettings()
+ .getCurrentLocale()); // Locale date display format
+ Revision.Format verstring = new Revision.Format(getProjectSettings()
+ .getRevisionPattern());
+ String path = _my.getSourceFile().getRelativePath();
+ String[] mapping = ApplicationSettings.getViewersMapping();
+
+ for (int i = 0; i < mapping.length; i++) {
+ org.splat.dal.bo.som.File export = _my.getAttachedFile(mapping[i]);
+ if (export != null) {
+ path = export.getRelativePath();
+ break;
+ }
+ }
+ _surl = getApplicationSettings().getRepositoryURL() + path;
+ _surl = _surl.replaceAll("'", "\\\\'");
+
+ // Document state (overridable by the publication - see below)
+ _state = _my.getProgressState();
+ _version = _my.getVersion(); // May be null
+
+ initIcons();
+
+ // Document description
+ VersionsRelation versions = (VersionsRelation) _my
+ .getFirstRelation(VersionsRelation.class);
+ if (versions != null) {
+ _description = versions.getDescription();
+ }
+ // File details
+ if (_state != ProgressState.EXTERN) {
+ _version = verstring.format(_version);
+ }
+ _size = sizstring.format(_my.getSourceFile().asFile().length() / 1000);
+ _date = datstring.format(_my.getLastModificationDate());
+
+ // Refresh of the history in case of promotion
+ if (_display == State.deepopen) {
+ _history.clear();
+ this.collectHistory(_my);
+ }
+ initPopupMenu();
+ }
+
+ /**
+ * Initialize document presentation icons.
+ */
+ private final void initIcons() {
+ // Icons definition
+ String format = _my.getFormat();
+ if ("xml".equals(format)) {
+ format = XMLDocument.getActualFormat(_my.getSourceFile().asFile());
+ }
+
+ _icon = "icon." + format + ICON_EXT;
+ _sharing = "image.hold.gif";
+ _updated = "image.hold.gif";
+ File image = new File(ApplicationSettings.getApplicationSkinPath()
+ + _icon);
+ if (!image.exists()) {
+ _icon = "icon.any.png";
+ }
+
+ if (_me == null) { // Facade in the history folder
+ if (_my.isVersioned()) { // History of the last version
+ if (_my.isPublished()) {
+ _sharing = "image.share.png"; // Not correct if published in a previous version of the study
+ _updated = "icon.hold.png";
+ }
+ } else {
+ if (_state == ProgressState.inWORK) {
+ _icon = "icon." + _state.toString() + ICON_EXT;
+ } else {
+ _icon = "icon.inWORK.png";
+ }
+ }
+ } else {
+ if (_me.getOwnerStudy().shares(_my)) {
+ _sharing = "image.share.png";
+ _updated = "icon.hold.png";
+ }
+ if (_me.isOutdated()) {
+ _state = ProgressState.inWORK; // Overrides the document state
+ }
+ }
+ }
+
+ /**
+ * Initialize document's popup menu.
+ */
+ private final void initPopupMenu() {
+ // Popup menus
+ if (_me != null) { // There is a pop-up
+ if (_state == ProgressState.EXTERN) {
+ _popup = getApplicationSettings().getPopupMenu("extern");
+ } else if (_state == ProgressState.inWORK) {
+ _popup = getApplicationSettings().getPopupMenu("editable");
+ } else if (_state == ProgressState.inDRAFT) {
+ _popup = getApplicationSettings().getPopupMenu("reviewable");
+ } else if (_state == ProgressState.APPROVED) {
+ _popup = getApplicationSettings().getPopupMenu("approved");
+ } else { // (state == ProgressState.inCHECK)
+ DocumentType aType = _me.value().getType(); // Only result documents need to be approved
+ Step aStep = getPublicationService().getInvolvedStep(_me);
+ if (aType.isResultOf(aStep.getStep())) {
+ _popup = getApplicationSettings()
+ .getPopupMenu("approvable");
+ } else {
+ _popup = getApplicationSettings().getPopupMenu("notresult");
+ }
+ }
+ }
+ }
+
+ /**
+ * Turn on the versioning icon.
+ */
+ protected void setVersioned() {
+ _updated = "image.modified.png";
+ }
+
+ // ==============================================================================================================================
+ // Private services
+ // ==============================================================================================================================
+
+ private final void collectHistory(final Document given) {
+ VersionsRelation versions = (VersionsRelation) given
+ .getFirstRelation(VersionsRelation.class);
+ Timestamp[] stamp = given.getStamps(); // Stamps in ascending order of date
+
+ for (int i = stamp.length - 1; i > -1; i--) {
+ _history.add(new StampFacade(stamp[i], getApplicationSettings()
+ .getCurrentLocale()));
+ }
+ _history.add(new DocumentFacade(_owner, given, getProjectSettings(),
+ getPublicationService(), getApplicationSettings()));
+ if (versions != null) {
+ this.collectHistory(versions.getTo());
+ }
+ }
+
+ /**
+ * Get project settings.
+ *
* @return Project settings service
*/
private ProjectSettingsService getProjectSettings() {
- return _projectSettingsService;
+ return _projectSettings;
}
/**
* Set project settings service.
- * @param projectSettingsService project settings service
+ *
+ * @param projectSettingsService
+ * project settings service
*/
- public void setProjectSettings(
- ProjectSettingsService projectSettingsService) {
- _projectSettingsService = projectSettingsService;
+ public final void setProjectSettings(
+ final ProjectSettingsService projectSettingsService) {
+ _projectSettings = projectSettingsService;
}
+
/**
* Get the publicationService.
*
* @param publicationService
* the publicationService to set
*/
- public void setPublicationService(PublicationService publicationService) {
+ public final void setPublicationService(
+ final PublicationService publicationService) {
_publicationService = publicationService;
}
+
+ /**
+ * Get the applicationSettings.
+ *
+ * @return the applicationSettings
+ */
+ public ApplicationSettings getApplicationSettings() {
+ return _applicationSettings;
+ }
+
+ /**
+ * Set the applicationSettings.
+ *
+ * @param applicationSettings
+ * the applicationSettings to set
+ */
+ public final void setApplicationSettings(
+ final ApplicationSettings applicationSettings) {
+ _applicationSettings = applicationSettings;
+ }
}
\ No newline at end of file