import org.opensim.modeling.*;
import java.io.IOException;
import static java.nio.file.StandardOpenOption.*;
import java.nio.file.*;

class TestEditProperties {
  public static void main(String[] args) {
    try {
        Model model = new Model("gait10dof18musc_subject01.osim");
        OpenSimContext context=null;
        long t1  = System.currentTimeMillis();
        try {
            context = new OpenSimContext(model.initSystem(), model);
        } catch (IOException ex) {
            ex.printStackTrace();
            System.out.println("Failed to initialize Context");
            System.exit(-1);
        }
        long t2  = System.currentTimeMillis();
        System.out.println("Model loading and initialization time (ms):"+(t2 - t1));
        Object gnd = model.getGround();
        Object gndValue = getValue(gnd);
        Body bdy = model.getBodySet().get("pelvis");
        AbstractProperty massProp = bdy.getPropertyByName("mass");
        Object massValue = getValue(massProp);
        // Now perform edits
        for (int ed=0; ed <10; ed++){
                double oldValue = PropertyHelper.getValueDouble(massProp);
                double v = oldValue+1.0;
                context.cacheModelAndState();
                PropertyHelper.setValueDouble(v, massProp);        
                try {
                    context.restoreStateFromCachedModel();
                } catch (IOException iae) {
                    PropertyHelper.setValueDouble(oldValue, massProp);
                    context.restoreStateFromCachedModel(); 
                    System.out.println("Failed to restore on failed edit");
                    System.exit(-1);
                } 
        }
		// Now edit a Vec6 Property (inertia)
		AbstractProperty inertiaProp = bdy.getPropertyByName("inertia");
		Vec6 oldInertia = new Vec6();
		for(int i=0; i<6; i++){
			oldInertia.set(i, PropertyHelper.getValueVec6(inertiaProp, i));
			System.out.println(oldInertia.get(i));
		}
		for(int i=0; i<6; i++){
			PropertyHelper.setValueVec6(i, inertiaProp, i); // Bad inertia matrix but we're just testing set/get'
		}
		Vec6 newInertia = new Vec6();
		for(int i=0; i<6; i++){
			double ret = PropertyHelper.getValueVec6(inertiaProp, i);
			newInertia.set(i, ret);
			System.out.println(newInertia.get(i));
			assert newInertia.get(i)==i;
		}
        long t3  = System.currentTimeMillis();
        System.out.println("Time to perform 10 edits (ms):"+(t3 - t2));
        System.out.println("Test finished!");
        System.exit(0);
    }
    catch(IOException ex){
        System.out.println("Failed to load model or in initSystem");
        System.exit(-1);
    }
    // TODO to cause test to fail: System.exit(-1);
  }

  static public Object getValue(Object propertyOrObject) {
      int idx = -1;
      if (propertyOrObject instanceof OpenSimObject)
        return ( (OpenSimObject) propertyOrObject).getName();
      else {
         AbstractProperty ap = (AbstractProperty)propertyOrObject;
         String propValueType = ap.getTypeName();
         //System.out.println("Processing property ["+ap.getName()+ "] type = ["+propValueType+"] index ="+idx);
         if (ap.isListProperty() && idx==-1 || ap.isOptionalProperty() && idx==-1)
             return ap.toString();
         if(propValueType.equalsIgnoreCase("double")) { 
            return PropertyHelper.getValueDouble(ap, idx);
         } else if(propValueType.equalsIgnoreCase("int")) {
            return PropertyHelper.getValueInt(ap, idx); 
         } else if(propValueType.equalsIgnoreCase("string")) {
            return PropertyHelper.getValueString(ap, idx);  
         } else if(propValueType.equalsIgnoreCase("bool")) {
            return PropertyHelper.getValueBool(ap, idx);
         } else if(propValueType.equalsIgnoreCase("Transform")) {
             return PropertyHelper.getValueTransform(ap, idx);
         } else if(propValueType.equalsIgnoreCase("Object")) {
            return ap.getValueAsObject();
         } else 
             return ap.toString();
      }
    }
}

@@ -1688,18 +1688,24 @@
       %7D%0A
-%09%09
+        
 // Now e
@@ -1734,18 +1734,24 @@
 nertia)%0A
-%09%09
+        
 Abstract
@@ -1807,18 +1807,24 @@
 rtia%22);%0A
-%09%09
+        
 Vec6 old
@@ -1837,34 +1837,40 @@
 a = new Vec6();%0A
-%09%09
+        
 for(int i=0; i%3C6
@@ -1877,19 +1877,28 @@
 ; i++)%7B%0A
-%09%09%09
+            
 oldInert
@@ -1953,19 +1953,28 @@
 p, i));%0A
-%09%09%09
+            
 System.o
@@ -2004,22 +2004,34 @@
 et(i));%0A
-%09%09%7D%0A%09%09
+        %7D%0A        
 for(int 
@@ -2050,58 +2050,19 @@
 +)%7B%0A
-%09%09%09PropertyHelper.setValueVec6(i, inertiaProp, i);
+           
  // 
@@ -2116,14 +2116,87 @@
 et'%0A
-%09%09%7D%0A%09%09
+            PropertyHelper.setValueVec6(i, inertiaProp, i); %0A        %7D%0A        
 Vec6
@@ -2221,18 +2221,24 @@
 Vec6();%0A
-%09%09
+        
 for(int 
@@ -2253,19 +2253,28 @@
 ; i++)%7B%0A
-%09%09%09
+            
 double r
@@ -2323,19 +2323,28 @@
 op, i);%0A
-%09%09%09
+            
 newInert
@@ -2359,19 +2359,28 @@
 , ret);%0A
-%09%09%09
+            
 System.o
@@ -2414,11 +2414,20 @@
 ));%0A
-%09%09%09
+            
 asse
@@ -2455,10 +2455,16 @@
 =i;%0A
-%09%09
+        
 %7D%0A  

Address feedback on PR tabs->spaces, linelength