/*
* 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;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import org.openrosa.client.java.io.DataInputStream;
import org.openrosa.client.java.io.DataOutputStream;
import org.openrosa.client.jr.core.model.utils.DateUtils;
import org.openrosa.client.jr.core.services.locale.Localizable;
import org.openrosa.client.jr.core.services.locale.Localizer;
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.ExtWrapListPoly;
import org.openrosa.client.jr.core.util.externalizable.ExtWrapNullable;
import org.openrosa.client.jr.core.util.externalizable.ExtWrapTagged;
import org.openrosa.client.jr.core.util.externalizable.PrototypeFactory;
/** The definition of a group in a form or questionaire.
*
* @author Daniel Kayiwa
*
*/
public class GroupDef implements IFormElement, Localizable {
private Vector children; /** A list of questions on a group. */
private boolean repeat; /** True if this is a "repeat", false if it is a "group" */
private int id; /** The group number. */
private IDataReference binding; /** reference to a location in the model to store data in */
private String labelInnerText;
private String appearanceAttr;
private String textID;
Vector observers;
public boolean noAddRemove = false;
public IDataReference count = null;
public GroupDef () {
this(Constants.NULL_ID, null, false);
}
public GroupDef(int id, Vector children, boolean repeat) {
setID(id);
setChildren(children);
setRepeat(repeat);
observers = new Vector();
}
public int getID () {
return id;
}
public void setID (int id) {
this.id = id;
}
public IDataReference getBind() {
return binding;
}
public void setBind(IDataReference binding) {
this.binding = binding;
}
public Vector getChildren() {
return children;
}
public void setChildren (Vector children) {
this.children = (children == null ? new Vector() : children);
}
public void addChild (IFormElement fe) {
children.addElement(fe);
}
public IFormElement getChild (int i) {
if (children == null || i >= children.size()) {
return null;
} else {
return (IFormElement)children.elementAt(i);
}
}
/**
* @return true if this represents a <repeat> element
*/
public boolean getRepeat () {
return repeat;
}
public void setRepeat (boolean repeat) {
this.repeat = repeat;
}
public String getLabelInnerText() {
return labelInnerText;
}
public void setLabelInnerText(String lit){
labelInnerText = lit;
}
public String getAppearanceAttr () {
return appearanceAttr;
}
public void setAppearanceAttr (String appearanceAttr) {
this.appearanceAttr = appearanceAttr;
}
public void localeChanged(String locale, Localizer localizer) {
for (Enumeration e = children.elements(); e.hasMoreElements(); ) {
((IFormElement)e.nextElement()).localeChanged(locale, localizer);
}
}
public IDataReference getCountReference() {
return count;
}
public String toString() {
return "<group>";
}
/*
* (non-Javadoc)
* @see org.javarosa.core.model.IFormElement#getDeepChildCount()
*/
public int getDeepChildCount() {
int total = 0;
Enumeration e = children.elements();
while(e.hasMoreElements()) {
total += ((IFormElement)e.nextElement()).getDeepChildCount();
}
return total;
}
/** Reads a group definition object from the supplied stream. */
public void readExternal(DataInputStream dis, PrototypeFactory pf) throws IOException, DeserializationException {
setID(ExtUtil.readInt(dis));
setAppearanceAttr((String)ExtUtil.read(dis, new ExtWrapNullable(String.class), pf));
setBind((IDataReference)ExtUtil.read(dis, new ExtWrapTagged(), pf));
setTextID((String)ExtUtil.read(dis, new ExtWrapNullable(String.class), pf));
setLabelInnerText((String)ExtUtil.read(dis, new ExtWrapNullable(String.class), pf));
setRepeat(ExtUtil.readBool(dis));
setChildren((Vector)ExtUtil.read(dis, new ExtWrapListPoly(), pf));
noAddRemove = ExtUtil.readBool(dis);
count = (IDataReference)ExtUtil.read(dis, new ExtWrapNullable(new ExtWrapTagged()), pf);
}
/** Write the group definition object to the supplied stream. */
public void writeExternal(DataOutputStream dos) throws IOException {
ExtUtil.writeNumeric(dos, getID());
ExtUtil.write(dos, new ExtWrapNullable(getAppearanceAttr()));
ExtUtil.write(dos, new ExtWrapTagged(getBind()));
ExtUtil.write(dos, new ExtWrapNullable(getTextID()));
ExtUtil.write(dos, new ExtWrapNullable(getLabelInnerText()));
ExtUtil.writeBool(dos, getRepeat());
ExtUtil.write(dos, new ExtWrapListPoly(getChildren()));
ExtUtil.writeBool(dos, noAddRemove);
ExtUtil.write(dos, new ExtWrapNullable(count != null ? new ExtWrapTagged(count) : null));
}
public void registerStateObserver (FormElementStateListener qsl) {
if (!observers.contains(qsl)) {
observers.addElement(qsl);
}
}
public void unregisterStateObserver (FormElementStateListener qsl) {
observers.removeElement(qsl);
}
public String getTextID() {
return textID;
}
public void setTextID(String textID) {
if(textID==null){
this.textID = null;
return;
}
if(DateUtils.stringContains(textID,";")){
System.err.println("Warning: TextID contains ;form modifier:: \""+textID.substring(textID.indexOf(";"))+"\"... will be stripped.");
textID=textID.substring(0, textID.indexOf(";")); //trim away the form specifier
}
this.textID = textID;
}
}