ENIGMA Forums

Outsourcing saves money => Issues Help Desk => Topic started by: egofree on May 30, 2014, 11:05:08 am

Title: Can't rename a resource under linux KDE
Post by: egofree on May 30, 2014, 11:05:08 am
Here is the error message :

Quote
java.lang.IllegalArgumentException: Comparison method violates its general contract!
   at java.util.TimSort.mergeHi(TimSort.java:868)
   at java.util.TimSort.mergeAt(TimSort.java:485)
   at java.util.TimSort.mergeForceCollapse(TimSort.java:426)
   at java.util.TimSort.sort(TimSort.java:223)
   at java.util.TimSort.sort(TimSort.java:173)
   at java.util.Arrays.sort(Arrays.java:659)
   at java.util.Collections.sort(Collections.java:217)
   at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(SortingFocusTraversalPolicy.java:136)
   at javax.swing.SortingFocusTraversalPolicy.getFocusTraversalCycle(SortingFocusTraversalPolicy.java:110)
   at javax.swing.SortingFocusTraversalPolicy.getComponentAfter(SortingFocusTraversalPolicy.java:280)
   at javax.swing.LayoutFocusTraversalPolicy.getComponentAfter(LayoutFocusTraversalPolicy.java:106)
   at sun.swing.SwingUtilities2.compositeRequestFocus(SwingUtilities2.java:1556)
   at javax.swing.plaf.basic.BasicTreeUI.startEditing(BasicTreeUI.java:2179)
   at javax.swing.plaf.basic.BasicTreeUI.startEditingAtPath(BasicTreeUI.java:618)
   at javax.swing.JTree.startEditingAtPath(JTree.java:2390)
   at org.lateralgm.main.Listener.actionPerformed(Listener.java:390)
   at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
   at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
   at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
   at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
   at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
   at javax.swing.AbstractButton.doClick(AbstractButton.java:356)
   at javax.swing.plaf.basic.BasicMenuItemUI$Actions.actionPerformed(BasicMenuItemUI.java:802)
   at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1662)
   at javax.swing.JComponent.processKeyBinding(JComponent.java:2869)
   at javax.swing.JMenuBar.processBindingForKeyStrokeRecursive(JMenuBar.java:689)
   at javax.swing.JMenuBar.processBindingForKeyStrokeRecursive(JMenuBar.java:697)
   at javax.swing.JMenuBar.processBindingForKeyStrokeRecursive(JMenuBar.java:697)
   at javax.swing.JMenuBar.processKeyBinding(JMenuBar.java:668)
   at javax.swing.KeyboardManager.fireBinding(KeyboardManager.java:307)
   at javax.swing.KeyboardManager.fireKeyboardAction(KeyboardManager.java:293)
   at javax.swing.JComponent.processKeyBindingsForAllComponents(JComponent.java:2961)
   at javax.swing.JComponent.processKeyBindings(JComponent.java:2953)
   at javax.swing.JComponent.processKeyEvent(JComponent.java:2832)
   at java.awt.Component.processEvent(Component.java:6282)
   at java.awt.Container.processEvent(Container.java:2229)
   at java.awt.Component.dispatchEventImpl(Component.java:4861)
   at java.awt.Container.dispatchEventImpl(Container.java:2287)
   at java.awt.Component.dispatchEvent(Component.java:4687)
   at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1895)
   at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:762)
   at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1027)
   at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:899)
   at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:727)
   at java.awt.Component.dispatchEventImpl(Component.java:4731)
   at java.awt.Container.dispatchEventImpl(Container.java:2287)
   at java.awt.Window.dispatchEventImpl(Window.java:2719)
   at java.awt.Component.dispatchEvent(Component.java:4687)
   at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
   at java.awt.EventQueue.access$200(EventQueue.java:103)
   at java.awt.EventQueue$3.run(EventQueue.java:694)
   at java.awt.EventQueue$3.run(EventQueue.java:692)
   at java.security.AccessController.doPrivileged(Native Method)
   at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
   at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
   at java.awt.EventQueue$4.run(EventQueue.java:708)
   at java.awt.EventQueue$4.run(EventQueue.java:706)
   at java.security.AccessController.doPrivileged(Native Method)
   at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
   at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
   at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
   at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
   at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
   at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
   at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
   at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

It happens only under linux. With Windows, it's fine.
Title: Re: Can't rename a resource under linux
Post by: Goombert on May 30, 2014, 09:58:48 pm
Sorry egofree, I am not able to reproduce this on Ubuntu. As you can see in the screenshot below I am able to rename resources fine using the right click menu, the edit box, or the edit menu. I also attempted loading another game and renaming resources as well as creating a blank game and one of every resource type and renaming each, and was still not able to reproduce the issue. Can I ask what resource type you are renaming, how you are renaming it, and what distro you are experiencing this under?

(http://i.imgur.com/31TB1iz.jpg)
Title: Re: Can't rename a resource under linux
Post by: egofree on May 31, 2014, 04:30:57 am
It happens with all resources, by double-clicking on it, or by pressing f2, or also with the contextual menu.
I've Linux Mint KDE 64 bits. It comes with OpenJDK. First i tried to remove OpenJDK and install instead the official Oracle version of Java. It doesn't change anything. Then, i tried to open the LateralGm code in Eclipse and to see why i had this error. But when i run the Lateralgm code from Eclipse i didn't have this error anymore !  ??? I did more tests, and i've found that if i run lateralgm.jar in another directory i don't have this error. (Of course if i run LateralGm alone i can't do much, but it's still possible to create a resource and to rename it). I did more tests, and i've found that if i rename the plugins folder in the enigma-dev folder, i don't have this error. I think the error must come from the jna.jar file. If i rename the enigma.jar file, i've still this error, and i can't run LateralGm if i try to change the name of the jna.jar file.
Title: Re: Can't rename a resource under linux
Post by: Goombert on May 31, 2014, 08:38:15 am
How are you launching LGM? I cd to enigma-dev then java -jar lateralgm.jar, make sure you cd to the dir that contains LGM. I promise you egofree, nothing has changed, it has always been this way.
Title: Re: Can't rename a resource under linux
Post by: egofree on May 31, 2014, 11:08:25 am
How are you launching LGM? I cd to enigma-dev then java -jar lateralgm.jar, make sure you cd to the dir that contains LGM. I promise you egofree, nothing has changed, it has always been this way.

Yes that's what i am doing. Perhaps it's because i am using the 64 bits version of Java. I tried to install first the 32 bits version of Java, but when i tried to run LateralGM, it didn't find some libraries needed to run awt and swing. It is looking for 32 bits libraries, but as my OS is 64 bits, only the 32 bits version are installed. I tried to install also 32 bits version of these libraries but i didn't succeed so far.
Title: Re: Can't rename a resource under linux
Post by: Goombert on May 31, 2014, 11:11:20 am
Oh that certainly could be causing issues, why not try a 32bit Java installation?
Title: Re: Can't rename a resource under linux
Post by: egofree on May 31, 2014, 11:12:22 am
Oh that certainly could be causing issues, why not try a 32bit Java installation?

Read my previous message !   :)
Title: Re: Can't rename a resource under linux
Post by: Goombert on May 31, 2014, 11:31:29 am
:O That shouldn't be happening though egofree, they are both a part of SE.
Title: Re: Can't rename a resource under linux
Post by: egofree on June 01, 2014, 07:13:34 am
I did more tests. First i tried on a virtual machine Linux Mint 16 KDE 32 bits with the oracle version of Java 32 bits. Same error. Then i tried Linux Cinnamon 32 bits and it didn't have this problem. Is this related to KDE ? I don't know, but i searched for the error message, and i've found this:

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7075600

and also:

Quote
It seems to me like you've hit a bug in the JDK since the error seems to come from Swing classes.

Options:

Define the property  java.util.Arrays.useLegacyMergeSort as true. Either using in your code the line

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
before any Swing code. As the first line in the main method should work.

Or adding

-Djava.util.Arrays.useLegacyMergeSort=true
to your starting options (in the console, or in the project properties in an IDE, Ant script, etc.)

Upgrade your JDK and see if the problem goes away

Downgrade to Java 6

http://stackoverflow.com/questions/13575224/comparison-method-violates-its-general-contract-timsort-and-gridlayout

It seems this error happens only on some systems with Java >= 7. So in LGM.java i added in the main method the following line :

Code: [Select]
public static void main(final String[] args)
{

....
   
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");

And i don't have anymore this error !  :) (Y)

Robert, as i don't know yet git very well, could you do for me a pull request with this line ?  :) Thanks in advance !

Update:
It seems Sort algorithm has changed since Java 7 :

Quote
Area: API: Utilities
Synopsis: Updated sort behavior for Arrays and Collections may throw an IllegalArgumentException
Description: The sorting algorithm used by java.util.Arrays.sort and (indirectly) by java.util.Collections.sort has been replaced. The new sort implementation may throw an IllegalArgumentException if it detects a Comparable that violates the Comparable contract. The previous implementation silently ignored such a situation.
If the previous behavior is desired, you can use the new system property, java.util.Arrays.useLegacyMergeSort, to restore previous mergesort behavior.
Nature of Incompatibility: behavioral
RFE: 6804124

http://www.oracle.com/technetwork/java/javase/compatibility-417013.html

Sort algorithm changes in Java 7:

http://dertompson.com/2012/11/23/sort-algorithm-changes-in-java-7/
Title: Re: Can't rename a resource under linux
Post by: Goombert on June 01, 2014, 10:45:20 am
Ugh, thanks for finding it out egofree. But I can't do that one line fix I don't think, I should actually fix the collection sorting. But also, this doesn't make sense, because renaming a resource in the tree does not do any sorting?
Title: Re: Can't rename a resource under linux
Post by: Josh @ Dreamland on June 01, 2014, 12:17:27 pm
You're doing it wrong; Windows should be inside the VM, and Xubuntu on the outside.
Title: Re: Can't rename a resource under linux
Post by: egofree on June 03, 2014, 03:45:11 am
But also, this doesn't make sense, because renaming a resource in the tree does not do any sorting?

I did more tests. I think it's not directly related to tree editing, but to some change in the focus between Lateralgm and its plugin. If the plugin is not loaded, you don't have this error.

In the error message, you can see :

Quote
   at sun.swing.SwingUtilities2.compositeRequestFocus(SwingUtilities2.java:1556)

And in order to have this focus Swing uses internally some arrays sorting. I've tested also Enigma with Kubuntu, and you have also this error ! It seems very likely that this error will happen with every distribution with KDE installed. I don't know how Swing works internally, but i guess depending on the OS and its graphics layer, some rendering and functionalities are not always working in the same way, even if in theory the result should be always the same.
The only possible fix i've found so far is adding in LateralGm:

Code: [Select]
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
Title: Re: Can't rename a resource under linux KDE
Post by: Goombert on June 04, 2014, 12:43:52 am
ego, how would we go about just putting LGM back into focus? It seems as though that would be technically more correct.
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on June 07, 2014, 08:55:16 am
I worked again on this bug. I think i've finally found the culprit ! >:( It seems it is the stopb button which is also managed in the plugin!! This button is used to stop the compiling process. It is enabled when we are starting the process, but anyway as far i can tell it is never displayed, so it is useless.
If i comment all lines which are related to this button in EnigmaRunner.java, the bug is gone. As this button is in fact never really used, what about removing this button and the corresponding stop menu ?

The stop menu and button are declared in EnigmaRunner.java :

Quote
public JMenuItem busy, run, debug, design, compile, rebuild, stop;
public JButton stopb, runb, debugb, compileb;

If you search the stopb and stop keywords, you will find only a few lines of code, so it is very easy to comment.

By the way, i tested the other day another distro of Linux Mint (i think it was Mate). This is non KDE, but still the bug is present in this distro.
Title: Re: Can't rename a resource under linux KDE
Post by: Goombert on June 07, 2014, 11:01:49 am
Thank you egofree, I will investigate, the button being there but hidden should not be causing errors.
Title: Re: Can't rename a resource under linux KDE
Post by: Goombert on June 07, 2014, 01:37:06 pm
Ok, as you said the exception is a bug in the JDK as a result of having a hidden button on the toolbar, the issue lies in the FocusTraversalPolicy. I have attempted to patch it by simply removing the button altogether from the toolbar until we are ready to add it. Please update and test.

You can rerun python install.py or you may also manually redownload the new plugin and LGM jars and replace them.
http://www.enigma-dev.org/docs/Wiki/Install:Extra_Packages
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on June 07, 2014, 02:48:43 pm
Robert, thanks a lot for you help, but are you sure you committed correctly your modification ?
To be sure, i did a new clean install (i deleted the enigma-dev folder), and i've still the error, but it seems the code for the button is still here. If i open in the enigma.jar file the EnigmaRunner.java file, the code for the button is still here:

Code: [Select]
public JMenuItem busy, run, debug, design, compile, rebuild, stop;
public JButton stopb, runb, debugb, compileb;

Code: [Select]
stop.setVisible(false);
stopb.setVisible(false);

Code: [Select]
public void populateMenu()
{
stopb = new JButton(); //$NON-NLS-1$
stopb.addActionListener(this);
stopb.setToolTipText(Messages.getString("EnigmaRunner.MENU_STOP"));
stopb.setIcon(LGM.getIconForKey("EnigmaPlugin.STOP"));
LGM.tool.add(new JToolBar.Separator(), 4);

Code: [Select]
public void compile(final int mode)
{
if (!assertReady()) return;

stop.setEnabled(true);
stopb.setEnabled(true);

etc..
Title: Re: Can't rename a resource under linux KDE
Post by: Goombert on June 07, 2014, 02:58:34 pm
What, let me check the hashes again, you can see here I've commented it out.
https://github.com/enigma-dev/lgmplugin/blob/master/org/enigma/EnigmaRunner.java#L410

Try manually downloading the plugin jar from here.
https://www.dropbox.com/s/bi2ws2jr53u9hsg/enigma.jar
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on June 07, 2014, 03:08:25 pm
What, let me check the hashes again, you can see here I've commented it out.
https://github.com/enigma-dev/lgmplugin/blob/master/org/enigma/EnigmaRunner.java#L410

Try manually downloading the plugin jar from here.
https://www.dropbox.com/s/bi2ws2jr53u9hsg/enigma.jar

Yes, i've downloaded also manually enigma.jar from the previous link. Try to open manually this jar and you will see that inside the enigmarunner.java doesn't have the updated version.
Title: Re: Can't rename a resource under linux KDE
Post by: Goombert on June 07, 2014, 03:12:44 pm
Wait, look the line should be commented add that adds stopb.
LGM.tool.add(new JToolBar.Separator(), 4);

The line directly after that, is it commented out or not?
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on June 07, 2014, 03:24:25 pm
Wait, look the line should be commented add that adds stopb.
LGM.tool.add(new JToolBar.Separator(), 4);

The line directly after that, is it commented out or not?

Ok the following line is commented, but i've still the error message. This afternoon i commented all lines concerning stopb, but this is easy to do :  if you do a search file with eclipse, in 30 seconds you can find and modify all lines. There must something like 10 lines to comment.

Edit :
If i remove line 169:

Code: [Select]
stopb.setVisible(false);
the error is also gone, but i find cleaner to comment all lines related to stopb.
Title: Re: Can't rename a resource under linux KDE
Post by: Goombert on June 07, 2014, 03:32:43 pm
Yes that's the bug because you can not traverse hidden buttons, also why it is only a bug in OpenJDK, again, it's fucking bullshit. But fine, I'll just comment all of it out.

Go ahead and redownload or python install.py
http://enigma-dev.org/docs/Wiki/Install:Extra_Packages
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on June 08, 2014, 04:24:40 am
I did more tests and i found that that you have to comment also the following line (404 in EnigmaRunner.java):

Code: [Select]
LGM.tool.add(new JToolBar.Separator(), 4);
Anyway this separator is never displayed. This is really strange i know. In the end, i wonder if there is some gremlins in my PC !  :D I need to take another aspirin  :ohdear: ;)
By the way i am not using OpenJDK, but Java Oracle !
Title: Re: Can't rename a resource under linux KDE
Post by: Goombert on June 08, 2014, 06:48:58 am
No that separator is definitely there, it is the separator on the toolbar directly after the create executable button. However it was being positioned improperly, I have now fixed that.

Try again by manually replacing the plugin jar or run python install.py
http://www.enigma-dev.org/docs/Wiki/Install:Extra_Packages
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on June 08, 2014, 07:37:31 am
No that separator is definitely there, it is the separator on the toolbar directly after the create executable button. However it was being positioned improperly, I have now fixed that.

Try again by manually replacing the plugin jar or run python install.py
http://www.enigma-dev.org/docs/Wiki/Install:Extra_Packages

Thanks Robert. I am traveling right now and i will test it next week.
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on June 09, 2014, 02:49:18 pm
The error is still here. :( In EnigmaRunner.java, the error comes now from :

Code: [Select]
LGM.tool.add(new JToolBar.Separator(), 8);
When we want to add a component in a toolbar at a given position, it seems to accept any component except a separator ! It doesn't trigger an error if you don't specify the position :

Code: [Select]
LGM.tool.addSeparator();
But of course, we don't want to add the separator at the end of the toolbar. I don't have for the moment a solution (Except the 'useLegacyMergeSort'  :D ).


Update :
Java : "Write once, run anywhere" Write once, test everywhere
:P
Title: Re: Can't rename a resource under linux KDE
Post by: Goombert on June 09, 2014, 04:04:33 pm
lol egofree, I'm empathetic to your troubles, I don't know wth to do

I have contacted IsmAvatar
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on June 10, 2014, 04:16:46 am
For the moment i see two solutions :

1) Creation of the Build menu in LateralGM. If the plugin is successfully loaded, LateralGM loads the menu and the toolbar. Everytime a menu or button is clicked, the plugin functions are called.

2) Using the following line :

Code: [Select]
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
I don't see any problem using the UseLEgacyMergeSort property. I think it is the easiest solution.

Edit:

3) I've seen the following code, in EnigmaRunner.java, in method subFrameAppeared :

Code: [Select]
status.add(new JLabel(" | ")); //$NON-NLS-1$
//visible divider       ^   since JSeparator isn't visible and takes up the whole thing...

What about using this instead of Separator ?

Edit2:

If i use :

Code: [Select]
LGM.tool.add(new JLabel("  "), 8);
Instead of

Code: [Select]
LGM.tool.add(new JToolBar.Separator(), 8);
Same error. So the error is not only happening with Separator.

Edit3:

If i add a JButton at position 8, the error happens also ! Too weird !. ???
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on June 10, 2014, 11:09:15 am
By the way, i invite you to attend to my Ph.D. defense. It will happen in M.I.T on June 2034, and the title is :

" In Java, how to insert a component in a toolbar : a 20-year study ! "

 (Y)  :)
Title: Re: Can't rename a resource under linux KDE
Post by: Goombert on June 10, 2014, 11:57:43 am
:)

Maybe it is because the index at which items remains static and it's pissed about two having the same index? Ugh.

You could also try changing uhm setFocusTraversalPolicy of the toolbar.
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on June 10, 2014, 12:57:18 pm
You could also try changing uhm setFocusTraversalPolicy of the toolbar.

Interesting. Within LateralGm, in the main method i've added the following code after the creation of the JFrame (line 843) :

Code: [Select]
final Container contentPane = LGM.frame.getContentPane();
Comparator<Component> comp = new Comparator<Component>() {
  public int compare(Component c1, Component c2) {
    Component comps[] = contentPane.getComponents();
    List<Component> list = Arrays.asList(comps);
    int first = list.indexOf(c1);
    int second = list.indexOf(c2);
    return second - first;
  }
};

FocusTraversalPolicy policy = new SortingFocusTraversalPolicy(comp);
frame.setFocusTraversalPolicy(policy);

I've found the code here : http://www.java2s.com/Code/JavaAPI/java.awt/ContainersetFocusTraversalPolicyFocusTraversalPolicypolicy.htm

I don't have anymore the error, and the focus traversal policy seems to work. However on the toolbar it doesn't seem to work anymore, but from my points of view it's not important. But is it the best way to fix this error ? I don't know. (At least the useLegacyMergeSort was only one line of code).


Title: Re: Can't rename a resource under linux KDE
Post by: Goombert on June 27, 2014, 04:25:46 am
I am still thinking about this one, but I think I would prefer to go with the verbose version purely because using legacy merge sort will not be an option in later Java releases.

egofree, could you also try upgrading to Java 8 or downgrading to 6? Or both?
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on June 27, 2014, 11:26:40 am
I am still thinking about this one, but I think I would prefer to go with the verbose version purely because using legacy merge sort will not be an option in later Java releases.

egofree, could you also try upgrading to Java 8 or downgrading to 6? Or both?

Thanks for not forgetting this problem. But i am already using Java 8 !
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on July 03, 2014, 02:19:12 am
Another solution would be to load in LateralGm the debug/run/compile buttons disabled by default. If the plugin is loaded, they would be enabled. Of course this solution would be less generic, but i guess it would fix the problem.
Title: Re: Can't rename a resource under linux KDE
Post by: Goombert on July 03, 2014, 03:36:03 am
That won't work ego, the whole point of the plugin is that LGM is its own program, it is separate from our project and can operate while being entirely isolated from a compiler.

But that is close to another solution, I am wondering if we added a callback in LGM for adding buttons to that toolbar if it wouldn't error.

Also I've filed a formal ticket for this.
https://github.com/IsmAvatar/LateralGM/issues/124
Title: Re: Can't rename a resource under linux KDE
Post by: egofree on July 25, 2014, 03:02:00 pm
If you change in preferences the icons to Swing, the bug is gone !  :o  Don't ask me why !   ;D
Title: Re: Can't rename a resource under linux KDE
Post by: Goombert on July 25, 2014, 08:24:55 pm
Probably because Swing doesn't have a run icon and therefore it may not even be adding the button to the toolbar?