Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Enumeration value " "/Space/Blank is generated to case class with blank/Space as name #181

Closed
tetanuss opened this Issue Dec 18, 2012 · 12 comments

Comments

Projects
None yet
4 participants

I have a problem with the following xsd snippet

                    <xs:element name="FillCharacter" default="">
                        <xs:annotation>
                            <xs:documentation>defines the possible fill charaters.
                                                    </xs:documentation>
                        </xs:annotation>
                        <xs:simpleType>
                            <xs:restriction base="xs:string">
                                <xs:length value="1"/>
                                <xs:enumeration value=" ">
                                    <xs:annotation>
                                        <xs:documentation>Space fill character.
                                        </xs:documentation>
                                    </xs:annotation>
                                </xs:enumeration>
                                <xs:enumeration value="0">
                                    <xs:annotation>
                                        <xs:documentation>0 fill character.
                                        </xs:documentation>
                                    </xs:annotation>
                                </xs:enumeration>
                            </xs:restriction>
                        </xs:simpleType>
                    </xs:element>

This snippet is evaluated to:

trait FillCharacter

object FillCharacter {
  def fromString(value: String): FillCharacter = value match {
    case " " => 
    case "0" => Number0

  }
}

case object   extends FillCharacter { override def toString = " " }
case object Number0 extends FillCharacter { override def toString = "0" }

Where I thought it should be something like

trait FillCharacter

object FillCharacter {
  def fromString(value: String): FillCharacter = value match {
    case " " => Space
    case "0" => Number0

  }
}

case object Space extends FillCharacter { override def toString = " " }
case object Number0 extends FillCharacter { override def toString = "0" }

The case class for the 0-Fillcharacter is generated in the right way with Name Number0.

Is there a workaround?

Owner

eed3si9n commented Dec 18, 2012

This is an interesting case. I probably could add some special rule for " ", but I am afraid someone else can come back with some other string that can't be used as a Scala identifier, like " " two spaces.
I am thinking about something more general like using Unicode number or halting the generation of enum values.

What about using the id instead of the value for generating the class name?

<xs:enumeration value=" " id="Space">

Then it should be explicit

Owner

eed3si9n commented Dec 18, 2012

id attribute is optional, so it can't be used reliably.

Maybe an other idea related to the class name of the '0' which is Number0. Why not generated a a class name Space1 to SpaceN where N stands for the number of Spaces. But this sounds for me like a hack.

Using the id to set the name of the class explicit sound for me like a valid clean solution, for the case the values are just like in the example. I know that this is not a common case - cause this xsd snippet comes from a really technical framework ;) - which runs right now with xstream generation in Java.

Seems that the workaround by using "\u0020" is OK.

                    <xs:element name="FillCharacter" default="\u0020">
                        <xs:annotation>
                            <xs:documentation>defines the possible fill charaters.
                            </xs:documentation>
                        </xs:annotation>
                        <xs:simpleType>
                            <xs:restriction base="xs:string">
                                <xs:length value="1"/>
                                <!--xs:enumeration value=" "-->
                                <xs:enumeration value="\u0020">
                                    <xs:annotation>`
                                        <xs:documentation>Space fill character.
                                        </xs:documentation>
                                    </xs:annotation>
                                </xs:enumeration>
                                <xs:enumeration value="0">
                                    <xs:annotation>
                                        <xs:documentation>0 fill character.
                                        </xs:documentation>
                                    </xs:annotation>
                                </xs:enumeration>
                            </xs:restriction>
                        </xs:simpleType>
                    </xs:element>

The result in the following code which should be OK.

trait FillCharacter

object FillCharacter {
  def fromString(value: String): FillCharacter = value match {
    case "\u0020" => U0020
    case "0" => Number0

  }
}

case object U0020 extends FillCharacter { override def toString = "\u0020" }
case object Number0 extends FillCharacter { override def toString = "0" }

But an enhancement still would be nice ;)

Owner

eed3si9n commented Dec 20, 2012

That's an interesting workaround since it exposes scalaxb's lack of handling backspace. In any case, this would allow me to publish 1.0 without implementing fixes, and hopefully I would address both the issues in 2.0.

I just tried this little peace of code to verify it

    var f = FillCharacter.fromString("0")
    println("X"+f+"X")
    f = FillCharacter.fromString(" ")
    println("X"+f+"X")
    f = FillCharacter.fromString("\u0020")
    println("X"+f+"X")

which gives me the output

X0X
X X
X X

and that's what I had assumed. All other values different than the three above give a match error. So the negative test is also OK. And doing it that way give you always a unique case class name.

I also tried to add the following

                                <xs:enumeration value="\u0020\u0020">
                                    <xs:annotation>
                                        <xs:documentation>One of the possible fill characters: 0.
                                        </xs:documentation>
                                    </xs:annotation>
                                </xs:enumeration>

which results to the code

trait FillCharacter

object FillCharacter {
  def fromString(value: String): FillCharacter = value match {
    case "\u0020" => U0020
    case "0" => Number0
    case "\u0020\u0020" => U0020u0020

  }
}

case object U0020 extends FillCharacter { override def toString = "\u0020" }
case object Number0 extends FillCharacter { override def toString = "0" }
case object U0020u0020 extends FillCharacter { override def toString = "\u0020\u0020" }

Nice! :)

gseitz commented Jan 11, 2013

You can also wrap the name in backticks, but using is arguably awkward to use and it also won't work with "", which unfortunately occurs in one of the schemas I have to use.

Owner

eed3si9n commented Apr 13, 2013

This was addressed in 1.0.2.

@eed3si9n eed3si9n closed this Apr 13, 2013

The fix unfortunately does not work with <xs:enumeration value="">, nor does it work with <xs:enumeration value="0">. Perhaps prepend names that don't start with a letter with __?

Owner

eed3si9n commented Jul 27, 2013

0 becomes Number0. I still need some special rule for `` I guess.

@eed3si9n eed3si9n reopened this Jul 27, 2013

Owner

eed3si9n commented Jul 30, 2013

Moving blank case to #220.

@eed3si9n eed3si9n closed this Jul 30, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment