/*
* Copyright (C) 2009 JavaRosa
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.openrosa.client.jr.core.model.data.helper;
import java.io.IOException;
import org.openrosa.client.java.io.DataInputStream;
import org.openrosa.client.java.io.DataOutputStream;
import org.openrosa.client.jr.core.model.QuestionDef;
import org.openrosa.client.jr.core.model.SelectChoice;
import org.openrosa.client.jr.core.util.externalizable.DeserializationException;
import org.openrosa.client.jr.core.util.externalizable.ExtUtil;
import org.openrosa.client.jr.core.util.externalizable.Externalizable;
import org.openrosa.client.jr.core.util.externalizable.PrototypeFactory;
/**
* A response to a question requesting a selection
* from a list.
*
* This class may exist in 3 states:
*
* 1) only index has a value
* 2) only xmlValue has a value
* 3) index, xmlValue, and choice have values, where index and xmlValue are simply cached copies of the values in 'choice'
*
* the 3rd form is the most full-featured, and is required for situations where you want to recover the captions for the
* choices, such as form entry. the choice objects used in the form entry model will receive localization updates,
* allowing you to retrieve the appropriate caption.
*
* the 2nd form is useful when dealing with FormInstances without having to worry about the FormDef or the captions
* from the <select> or <select1> controls. this form contains enough information to convert to an XML instance
*
* the 1st form is used when serializing instances in an ultra-compact manner, but requires linking to a FormDef before
* you can do anything useful with the instance (insufficient info to convert to XML instance).
*
* @author Drew Roos
*
*/
public class Selection implements Externalizable {
public String xmlValue = null;
public int index = -1;
/* in order to get localizable captions for this selection, the choice object must be the
* same object in the form model, or else it won't receive localization updates from form
* entry session
*/
public SelectChoice choice;
/**
* for deserialization only
*/
public Selection() {
}
public Selection (SelectChoice choice) {
attachChoice(choice);
}
public Selection (String xmlValue) {
this.xmlValue = xmlValue;
}
public Selection (int index) {
this.index = index;
}
public Selection clone () {
Selection s = new Selection();
s.choice = choice;
s.xmlValue = xmlValue;
s.index = index;
return s;
}
public void attachChoice (SelectChoice choice) {
this.choice = choice;
this.xmlValue = choice.getValue();
this.index = choice.getIndex();
}
public void attachChoice (QuestionDef q) {
if (q.getDynamicChoices() != null) //can't attach dynamic choices because they aren't guaranteed to exist yet
return;
SelectChoice choice = null;
if (index != -1 && index < q.getNumChoices()) {
choice = q.getChoice(index);
} else if (xmlValue != null && xmlValue.length() > 0) {
choice = q.getChoiceForValue(xmlValue);
}
if (choice != null) {
attachChoice(choice);
} else {
throw new RuntimeException("insufficient data in selection to reconstruct");
}
}
// @Deprecated
// public String getText () {
// if (choice != null) {
// return choice.getCaption();
// } else {
// System.err.println("Warning!! Calling Selection.getText() when Choice object not linked!");
// return "[cannot access choice caption]";
// }
// }
public String getValue () {
if (xmlValue != null && xmlValue.length() > 0) {
return xmlValue;
} else {
throw new RuntimeException("don't know xml value! perhaps selection was stored as index only and has not yet been linked up to a formdef?");
}
}
/* (non-Javadoc)
* @see org.javarosa.core.services.storage.utilities.Externalizable#readExternal(java.io.DataInputStream)
*/
public void readExternal(DataInputStream in, PrototypeFactory pf) throws IOException, DeserializationException {
xmlValue = ExtUtil.readString(in);
index = ExtUtil.readInt(in);
}
/* (non-Javadoc)
* @see org.javarosa.core.services.storage.utilities.Externalizable#writeExternal(java.io.DataOutputStream)
*/
public void writeExternal(DataOutputStream out) throws IOException {
ExtUtil.writeString(out, getValue());
ExtUtil.writeNumeric(out, index);
}
}