SageTV Community  

Go Back   SageTV Community > SageTV Development and Customizations > SageTV Studio
Forum Rules FAQs Community Downloads Today's Posts Search

Notices

SageTV Studio Discussion related to the SageTV Studio application produced by SageTV. Questions, issues, problems, suggestions, etc. relating to the Studio software application should be posted here.

Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old 02-23-2010, 06:33 PM
PLUCKYHD PLUCKYHD is offline
SageTVaholic
 
Join Date: Dec 2007
Posts: 6,257
Easy way to dynamically build classes/objects

So wondering if there is an easier way to dynamically define and build custom class's which are for javaobjects.

For instance say I have

Code:
class BookObject{

private string Bookname;
private int BookLocation;

public String GetBookname(){
return Bookname;}
public void SetBookname(String Value){
this.Bookname=Value}
public Integer GetBookLocation(){
return BookLocation;}
public void setBookLocation(int Value){
this.BookLocation=Value;}
}
Is there a easier way to build this dynamically wihtout having to add Get/Set calls for every variable the object will hold? I figure there has to be and I am missing it?

maybe not....

cheers and TIA

pluckyhd
Reply With Quote
  #2  
Old 02-23-2010, 07:20 PM
GKusnick's Avatar
GKusnick GKusnick is offline
SageTVaholic
 
Join Date: Dec 2005
Posts: 5,083
In what sense would this be dynamic? Presumably you're not planning to generate new classes and methods at runtime. You're going to code them once and that's it. So what you're looking for (if I understand right) is a way to save some typing when coding up new classes.

Seems to me the simplest solution is to make those fields public instead of private, so clients of your class can access them directly instead of through getter/setter methods. Or is there some other reason you need explicit getter/setter methods?
__________________
-- Greg
Reply With Quote
  #3  
Old 02-23-2010, 07:41 PM
PLUCKYHD PLUCKYHD is offline
SageTVaholic
 
Join Date: Dec 2007
Posts: 6,257
Quote:
Originally Posted by GKusnick View Post
In what sense would this be dynamic? Presumably you're not planning to generate new classes and methods at runtime. You're going to code them once and that's it. So what you're looking for (if I understand right) is a way to save some typing when coding up new classes.
Correct want to save allot of typing/time.

Quote:
Originally Posted by GKusnick View Post
Seems to me the simplest solution is to make those fields public instead of private, so clients of your class can access them directly instead of through getter/setter methods. Or is there some other reason you need explicit getter/setter methods?

No other reason than that is how I learned how to do it...Is there a way to set those variables without set methods?
Reply With Quote
  #4  
Old 02-23-2010, 07:43 PM
Fuzzy's Avatar
Fuzzy Fuzzy is offline
SageTVaholic
 
Join Date: Sep 2005
Location: Jurupa Valley, CA
Posts: 9,957
There's really no reason to use Get and Sets if all they really do is manipulate the internal variable without any other checks/functions. It's easier to just make the variable itself public. Just make it as so:

Code:
class BookObject{

public string Bookname;
public int BookLocation;

}
there are, of course, times when you want the variable itself to be private, and use gets and sets... but that would be if you wanted to actually DO something in that get or set function, like check the data before writing, and potentially throw some errors... or provide logging, etc...
__________________
Buy Fuzzy a beer! (Fuzzy likes beer)

unRAID Server: i7-6700, 32GB RAM, Dual 128GB SSD cache and 13TB pool, with SageTVv9, openDCT, Logitech Media Server and Plex Media Server each in Dockers.
Sources: HRHR Prime with Charter CableCard. HDHR-US for OTA.
Primary Client: HD-300 through XBoxOne in Living Room, Samsung HLT-6189S
Other Clients: Mi Box in Master Bedroom, HD-200 in kids room
Reply With Quote
  #5  
Old 02-23-2010, 08:00 PM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,713
Pluckly, most IDEs will do this for your.

Just create,
Code:
public class class BookObject {
   private string Bookname;
   private int BookLocation;
}
Then right click, and Source -> Generate Getters and Setters. The ide will create all the setters and getters.

Later when you add
Code:
private long price;
then right click, Source -> Generate Getters and Setters, and the IDE will fill in the missing methods.

If you use netbeans, then it has the same tools, but may be called something slightly different.

Keep in mind, that java ides (like most ides) will generate tons of boilerplate code. nobody write that stuff anymore.
Reply With Quote
  #6  
Old 02-23-2010, 08:12 PM
GKusnick's Avatar
GKusnick GKusnick is offline
SageTVaholic
 
Join Date: Dec 2005
Posts: 5,083
Quote:
Originally Posted by PLUCKYHD View Post
Is there a way to set those variables without set methods?
object.field = value;

(Assuming the field is public of course.)
__________________
-- Greg
Reply With Quote
  #7  
Old 02-23-2010, 10:18 PM
Slugger Slugger is offline
SageTVaholic
 
Join Date: Mar 2007
Location: Kingston, ON
Posts: 4,008
Please do not use public properties for your class, especially if the class is to be part of a public API that you plan to release. Call me "old school", but simply making your properties public will undoubtedly cost you down the road.

Code:
public class Book {
   public String title;
   public String content; // Assume content is just one big string for simplicity
   public int numPages;
   public int location;

   public Book(String title, String content, int numPages, int location) {
      this.title = title;
      this.content = content;
      this.numPages = numPages;
      this.location = location;
   }
}
So to make life easier you make these properties public and allow direct access and modification to them. All is good until somewhere down the road you accidentally instantiate an instace of Book like this:

Code:
Book b = new Book("My First Novel", "Blah blah blah", -1, 200);
And somewhere else in your code you get an IndexOutOfBoundsException (or some kind of runtime exception) because numPages is negative. So you track down the bug and the sol'n is to ensure that numPages is never negative. You could check this in the constructor, but what happens when the value is set to negative after instantiation?

Code:
Book b = new Book("My Novel", "Blah, blah, blah", 5, 200); // Valid object instantiation
b.numPages = -1;  // Completely valid since numPages is public, but now numPages is negative, which will cause that runtime error to resurface
The only way to ensure numPages is never negative is to control the setting of the value via a method:

Code:
public class Book {
   private String title;
   private String content; // Assume content is just one big string for simplicity
   private int numPages;
   private int location;

   public Book(String title, String content, int numPages, int location) {
      if(numPages < 0)
         throw new IllegalArgumentException("Number of pages cannot be negative!");
      this.title = title;
      this.content = content;
      this.numPages = numPages;
      this.location = location;
   }

   public int getNumPages() {
      return numPages;
   }

   public void setNumPages(int num) {
      if(num < 0)
         throw new IllegalArgumentException("Number of pages cannot be negative!");
      numPages = num;
   }
}
If you made the properties public then made them private to address the issue then you've now also broken all consumers of the class, which just adds more work. Put the extra work in up front and save yourself a headache later. Any decent IDE (I use Eclipse) will create the public getters and setters for you based on your private properties of the class. Take advantage of that, but trust me when I say don't just go making all your class properties public from the start.

My CS201 Prof would be so proud of me right now. And this also proves, despite his claim, that one can learn something even while napping during those 8am lectures!
__________________
Twitter: @ddb_db
Server: Intel i5-4570 Quad Core, 16GB RAM, 1 x 128GB OS SSD (Win7 Pro x64 SP1), 1 x 2TB media drive
Capture: 2 x Colossus
STB Controller: 1 x USB-UIRT
Software:Java 1.7.0_71; SageTV 7.1.9
Clients: 1 x HD300, 2 x HD200, 1 x SageClient, 1 x PlaceShifter
Plugins: Too many to list now...

Last edited by Slugger; 02-23-2010 at 10:26 PM.
Reply With Quote
  #8  
Old 02-24-2010, 02:01 AM
GKusnick's Avatar
GKusnick GKusnick is offline
SageTVaholic
 
Join Date: Dec 2005
Posts: 5,083
Quote:
Originally Posted by Slugger View Post
...trust me when I say don't just go making all your class properties public from the start.
Not all of them, certainly, but if there's (say) an integer property that can legitimately take on any integer value, then I don't see the harm in making it public and avoiding the overhead of getter/setter methods.

Quote:
Originally Posted by Slugger View Post
If you made the properties public then made them private to address the issue then you've now also broken all consumers of the class...
Point taken, but to my mind this is a deficiency in Java, for which the workaround is to pre-emptively use getter/setter methods and force consumers to use method call syntax instead of the more natural assignment syntax. Other languages (such as VB and C#) handle this situation better by allowing consumers to be agnostic about whether they're accessing a property directly or through getter/setter methods and use assignment syntax in either case. This gives the class designer the freedom to change the implementation without breaking existing consumers. So while obsessive use of getters/setters may be appropriate for Java, it's not a habit one should carry over to other languages that don't require it.
__________________
-- Greg
Reply With Quote
  #9  
Old 02-24-2010, 06:34 AM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,713
I agree with Slugger here... do start out by exposing properties, it's just wrong, for an object.

Now, if you are truly making a structure (ie, what's we'd call a struct in c), then I could see, perhaps, not creating the setters and getters. There are cases where i've done this for inner classes that are being uses only to hold data, ie, there are no operations in the structs. My general rule of thumb here, is the struct instances are never exposed beyond my class, and that the structs do not contain methods.

So, if you objects are purely structs, then I could see someone just using properties. The problem is your objects are going to start out as structs, and then you are going to add in constructors with parameters and method that calculate values, and now you have this crud of an object/struct that doesn't make sense to anyone.

Greg's point above is valid, ie, he way that c# defines setters and getters is better. But given that an ide will generate setters and getters for you in a couple seconds... is there really any reason to choose poor coding conventions, when doing it right, is just so darn easy
Reply With Quote
  #10  
Old 02-24-2010, 06:41 AM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,713
Quote:
Originally Posted by GKusnick View Post
Point taken, but to my mind this is a deficiency in Java, for which the workaround is to pre-emptively use getter/setter methods and force consumers to use method call syntax instead of the more natural assignment syntax. Other languages (such as VB and C#) handle this situation better by allowing consumers to be agnostic about whether they're accessing a property directly or through getter/setter methods and use assignment syntax in either case. This gives the class designer the freedom to change the implementation without breaking existing consumers. So while obsessive use of getters/setters may be appropriate for Java, it's not a habit one should carry over to other languages that don't require it.
Part of what makes a good programmer is there ability to adapt to different programming languages. When I write C code, I don't write it in the "java way", and when I write Java code, and I don't write it in the "C" way (although I was a C programmer first). Adapting the language is good for you, and it's even better for the person that has to clean up after you. Do you realize how hard it is for someone to work on java code that been coded in c, or vice versa? Your other point about allowing the developer to use either field notation or method notation for accessing the same value (or setting it)... there's something to be said for consistency. I laugh when I see vb and .net code where parts of the program use object.field and later they use object.getField()... I think this usually stems from different people working the same file, who refuse to adapt to the way it's been previously done.
Reply With Quote
  #11  
Old 02-24-2010, 07:02 AM
PLUCKYHD PLUCKYHD is offline
SageTVaholic
 
Join Date: Dec 2007
Posts: 6,257


Did not know about the auto set/getter coding do you know how much time that would have saved me 3 months ago if I would have asked

I prefer to leave them private and my reasons are different from above and I didn't mean to start an argument.

The method I read and use it to make all of the private in the object class and have another class for calling the methods it is allot of coding but it is easier for me to keep track of that way.

thanks again and I can't believe I didn't know about the automatic set/get methods of the ide....
Reply With Quote
  #12  
Old 02-24-2010, 07:50 AM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,713
@Plucky - don't feel bad. I've pointed out features of eclipse to people that have been using for longer than I have Keep in mind, then only reason to use an IDE is increase productivity over a regular power editor like vim. I spent years in vim, so when I moved to eclipse, I needed to prove that it would actually increase my productivity. While initially, learning every aspect of the IDE decreased my productivity, doing so has much improved my overall productivity, and then I stopped using vim (i still miss vim )

Bottom line keep posting your questions... whenever you think that "there's got to be an easier way..." there probably is... because we also hate typing
Reply With Quote
  #13  
Old 02-24-2010, 09:19 AM
jphipps jphipps is offline
Sage Expert
 
Join Date: Aug 2006
Location: Maryland
Posts: 512
Quote:
Originally Posted by stuckless View Post
@Plucky - don't feel bad. I've pointed out features of eclipse to people that have been using for longer than I have Keep in mind, then only reason to use an IDE is increase productivity over a regular power editor like vim. I spent years in vim, so when I moved to eclipse, I needed to prove that it would actually increase my productivity. While initially, learning every aspect of the IDE decreased my productivity, doing so has much improved my overall productivity, and then I stopped using vim (i still miss vim )

Bottom line keep posting your questions... whenever you think that "there's got to be an easier way..." there probably is... because we also hate typing
That is one thing I like about netbeans, they have a vi plugin jvi to make the editor use all vi commands instread of the normal gui editor...

Thanks,
Jeff
Reply With Quote
  #14  
Old 02-24-2010, 10:11 AM
Fuzzy's Avatar
Fuzzy Fuzzy is offline
SageTVaholic
 
Join Date: Sep 2005
Location: Jurupa Valley, CA
Posts: 9,957
Wow.. this discussion really has pointed out how happy i am that I use .net languages.. ;-) I make a custom class for just about every object I use, and the agnostic nature of properties and variables are so much more evolved than the older java and c methods. I hadn't realized the difference when I recommended just majing the variables themselves public earlier. If you can't use them in the same way as get/set methods in subsequent code, then, yes, it does only make sense to ONLY use get and set methods.

In .NET, however, if you are not going to be doing any checking of a value before setting it, or not performing any action when get or set, then there really is no harm in making the variables themselves public. If at a later time, you decide there are some checks and what-not that you wish to perform, you can easily create a private variable to take it's place, and make a public property (the .net name for getters and setters) with the same name... makes it a transparent change to the users of the class.
__________________
Buy Fuzzy a beer! (Fuzzy likes beer)

unRAID Server: i7-6700, 32GB RAM, Dual 128GB SSD cache and 13TB pool, with SageTVv9, openDCT, Logitech Media Server and Plex Media Server each in Dockers.
Sources: HRHR Prime with Charter CableCard. HDHR-US for OTA.
Primary Client: HD-300 through XBoxOne in Living Room, Samsung HLT-6189S
Other Clients: Mi Box in Master Bedroom, HD-200 in kids room
Reply With Quote
  #15  
Old 02-24-2010, 10:46 AM
Slugger Slugger is offline
SageTVaholic
 
Join Date: Mar 2007
Location: Kingston, ON
Posts: 4,008
Hopefully no one else is seeing this as an argument, but rather a valid discussion on coding practices. I hope my tone is not being read as anything other than that.

Quote:
Point taken, but to my mind this is a deficiency in Java, for which the workaround is to pre-emptively use getter/setter methods and force consumers to use method call syntax instead of the more natural assignment syntax. Other languages (such as VB and C#) handle this situation better by allowing consumers to be agnostic about whether they're accessing a property directly or through getter/setter methods and use assignment syntax in either case. This gives the class designer the freedom to change the implementation without breaking existing consumers. So while obsessive use of getters/setters may be appropriate for Java, it's not a habit one should carry over to other languages that don't require it.
I wouldn't call it a deficiency, but rather a difference between Java and VB or C#. Don't quote me on this (b/c I can't find the reference and I'm just working solely from memory on this), but I believe the reason Java doesn't provide such syntactic sugar (which is really all it is in VB/C#) is because Gosling despised the syntactic sugar provided by C++ at the time, namely operator overloading. Instead he felt it was much easier to understand a programmer's intent through the use of explicit getters/setters rather than allowing all kinds of syntactic sugar/implied code. When I first started with Java (coming from a C/C++ background) I have to admit I disagreed and missed my operator overloading from C++. Years later, I now appreciate the explicitness of Java code versus reading some crazy C++ code from some hotshot who felt it was "cool" to overload the bit shift operator to mean "clone" without solid docs. You sit and scratch your head for hours and hours trying to figure out what's going on, whereas if the code just read:

Code:
// Not real var names, bare with me ;)
MyObj *obj;
MyObj *obj2;
...
obj->clone(obj2);
Then I'd have saved myself a massive migraine. I'm not saying there's no place for syntactic sugar, but my experience has been that too many devs take advantage of it without properly documenting it, whereas if they had to use explicit method calls then their code becomes self documenting and much clearer. This may not be relevant in the space of SageTV development where most projects are single authors, but still always a good practice.
__________________
Twitter: @ddb_db
Server: Intel i5-4570 Quad Core, 16GB RAM, 1 x 128GB OS SSD (Win7 Pro x64 SP1), 1 x 2TB media drive
Capture: 2 x Colossus
STB Controller: 1 x USB-UIRT
Software:Java 1.7.0_71; SageTV 7.1.9
Clients: 1 x HD300, 2 x HD200, 1 x SageClient, 1 x PlaceShifter
Plugins: Too many to list now...
Reply With Quote
  #16  
Old 02-24-2010, 11:00 AM
Slugger Slugger is offline
SageTVaholic
 
Join Date: Mar 2007
Location: Kingston, ON
Posts: 4,008
Quote:
Originally Posted by GKusnick View Post
Not all of them, certainly, but if there's (say) an integer property that can legitimately take on any integer value, then I don't see the harm in making it public and avoiding the overhead of getter/setter methods.
Until such time someone (maybe you, maybe someone else) decides that the int property can no longer take on a certain set of values. If you put the work in up front then it's just a matter of enforcing the new requirement in the setter (and perhaps ctor) and releasing the new jar, but if you made the property public then now you have to break all consumers and label your new version as an API breaking update to your API, which is very bad news.

Again, I guess I'm speaking more from my day job when I talk about this kind of thing and I'm sure if you go looking through my source code for all my SageTV plugins you'll find some direct contradictions to my advice (though I'd be shocked if you found a public property defined in any public or pkg protected class that I've written), but, imho, when it comes to Java there's just no reason not to create getters and setters for all class properties. If nothing else, it's preventative maintenance and will save a (possible) API breaking fix later on down the road.
__________________
Twitter: @ddb_db
Server: Intel i5-4570 Quad Core, 16GB RAM, 1 x 128GB OS SSD (Win7 Pro x64 SP1), 1 x 2TB media drive
Capture: 2 x Colossus
STB Controller: 1 x USB-UIRT
Software:Java 1.7.0_71; SageTV 7.1.9
Clients: 1 x HD300, 2 x HD200, 1 x SageClient, 1 x PlaceShifter
Plugins: Too many to list now...
Reply With Quote
  #17  
Old 02-24-2010, 11:15 AM
Fuzzy's Avatar
Fuzzy Fuzzy is offline
SageTVaholic
 
Join Date: Sep 2005
Location: Jurupa Valley, CA
Posts: 9,957
well, to be fair, there's a HUGE difference in the 'sugar' in C++ (which is very inconsistant, and almost 'tacked on' feeling) and .NET's much more natural way of doing things. Of course, a lot of the power of .net IS the visual studio IDE. Why have the code 'self-documenting' just through comments and method names, when you can have the applicable documentation popping up as you are coding?

Attached Images
File Type: gif WhoDaFoo.gif (7.2 KB, 289 views)
__________________
Buy Fuzzy a beer! (Fuzzy likes beer)

unRAID Server: i7-6700, 32GB RAM, Dual 128GB SSD cache and 13TB pool, with SageTVv9, openDCT, Logitech Media Server and Plex Media Server each in Dockers.
Sources: HRHR Prime with Charter CableCard. HDHR-US for OTA.
Primary Client: HD-300 through XBoxOne in Living Room, Samsung HLT-6189S
Other Clients: Mi Box in Master Bedroom, HD-200 in kids room
Reply With Quote
  #18  
Old 02-24-2010, 12:12 PM
stuckless's Avatar
stuckless stuckless is offline
SageTVaholic
 
Join Date: Oct 2007
Location: London, Ontario, Canada
Posts: 9,713
Quote:
Originally Posted by Fuzzy View Post
well, to be fair, there's a HUGE difference in the 'sugar' in C++ (which is very inconsistant, and almost 'tacked on' feeling) and .NET's much more natural way of doing things. Of course, a lot of the power of .net IS the visual studio IDE. Why have the code 'self-documenting' just through comments and method names, when you can have the applicable documentation popping up as you are coding?

I'd be very disappointed in an IDE that didn't do that... other than standard editors, I'm pretty sure every IDE would do auto completion and hovering documentation, click through navigation of objects (ie, in eclpse, if you hover on a type, class, field, etc, and hold the ctrl key, then it turns that item into an hyperlink where you can click it to jump directly to that declaration, class file, etc.).

I think "natural" is a term that people use to describe the way that they currently do things
Reply With Quote
  #19  
Old 02-24-2010, 12:22 PM
Fuzzy's Avatar
Fuzzy Fuzzy is offline
SageTVaholic
 
Join Date: Sep 2005
Location: Jurupa Valley, CA
Posts: 9,957
I was in no way stating that eclipse can't do this, just that THIS is how code should be documented, not just with Method names. I actually think Stuff = GetThis and SetThat(stuff) are an extra level of unnecessary complexity... I much prefer Stuff = This and That = Stuff... Much easier to read through the code. Never liked that Java forced you to use two completly different styles for variables and functions..
__________________
Buy Fuzzy a beer! (Fuzzy likes beer)

unRAID Server: i7-6700, 32GB RAM, Dual 128GB SSD cache and 13TB pool, with SageTVv9, openDCT, Logitech Media Server and Plex Media Server each in Dockers.
Sources: HRHR Prime with Charter CableCard. HDHR-US for OTA.
Primary Client: HD-300 through XBoxOne in Living Room, Samsung HLT-6189S
Other Clients: Mi Box in Master Bedroom, HD-200 in kids room
Reply With Quote
  #20  
Old 02-24-2010, 01:32 PM
evilpenguin's Avatar
evilpenguin evilpenguin is offline
SageTVaholic
 
Join Date: Aug 2003
Location: Seattle, WA
Posts: 3,696
Quote:
Originally Posted by stuckless View Post
I'd be very disappointed in an IDE that didn't do that... other than standard editors, I'm pretty sure every IDE would do auto completion and hovering documentation, click through navigation of objects (ie, in eclpse, if you hover on a type, class, field, etc, and hold the ctrl key, then it turns that item into an hyperlink where you can click it to jump directly to that declaration, class file, etc.).

I think "natural" is a term that people use to describe the way that they currently do things
Man, my IDE doesn't do any of this stuff, maybe I just don't have it set up right...

Attached Images
File Type: jpg whyCantMyIDEdoThat.jpg (113.5 KB, 315 views)
__________________
Clients: 1xHD200 Connected to 50" TH-50PZ750U Plasma
Server : Shuttle SFF SSH55J2 w/ Win7 Home, SageTV v7, Core i3 540, 2GB RAM, 30GB SSD for OS, 1.5TB+2x1TB WDGP for Recordings, BluRay, 2xHDHR, 1xFirewire
SageTV : PlayOn, SJQ, MediaShrink, Comskip, Jetty, Web Client, BMT


Having a problem? Don't forget to include a log! (Instructions for: PlayOn For SageTV v1.5, MediaShrink)
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Any experience in Sun online classes? PLUCKYHD SageTV Studio 5 03-23-2010 03:20 AM
Moving objects leaving trails(after images) xxilikedirtxx Hardware Support 1 02-20-2006 05:58 PM
Dynamically loading/unloading STV MadAxeMan SageTV Studio 0 01-26-2006 05:05 AM
Moving objects flashing - interlace issue? lbeagley79 Hardware Support 15 10-14-2005 08:34 AM
Dynamically Select Live TV Capture Device kkoz SageTV Software 0 07-14-2005 11:27 AM


All times are GMT -6. The time now is 12:57 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2023, vBulletin Solutions Inc.
Copyright 2003-2005 SageTV, LLC. All rights reserved.