This is an old revision of the document!


CRUD

CRUD is a SOLoist sample application, a simple demo of a classical CRUD (Create, Read, Update, Delete) pattern for objects of a class.

The left-hand list box renders all objects of the class Person. When one is selected, its Bank Accounts are listed in the list box in the middle. When a Bank Account is selected, its slots can be edited in the slot editors on the right. A new Bank Account can be created, or an existing one can be deleted with the generic commands (the buttons at the bottom).

Live example

UML Model

Business Logic Code

CreateAccountForPerson.java
public void execute() 
    // -------------<SOL id="399df754-74dc-47d2-bf14-83e6961185f2:___throw__" />
    // -------------<LOS id="399df754-74dc-47d2-bf14-83e6961185f2:___throw__" />
    {
        // ---------<SOL id="399df754-74dc-47d2-bf14-83e6961185f2:___body___" />
        Person p = person.val();
        if (p == null)
        {
        	throw new CommandPreconditionsException("Please, select person first.");
        }
 
        BankAccount ba = new BankAccount();
        ba.number.set(Text.fromString("xxx-xxx-xxx"));
        ba.amount.set(Currency.fromBigDecimal(BigDecimal.valueOf(0.)));
        ba.bankName.set(Text.fromString("New Bank"));
 
        p.accounts.add(ba);
        // ---------<LOS id="399df754-74dc-47d2-bf14-83e6961185f2:___body___" />
    }

GUI Code

package rs.sol.sampleapps;
 
import rs.sol.sampleapps.commands.CreateAccountForPerson;
import rs.sol.soloist.helpers.init.DefaultContextInit;
import rs.sol.soloist.helpers.init.Initializer;
import rs.sol.soloist.helpers.init.InitializerFailedException;
import rs.sol.soloist.server.builtindomains.builtincommands.CmdDestroyObject;
import rs.sol.soloist.server.builtindomains.builtindatatypes.Text;
import rs.sol.soloist.server.guiconfiguration.components.GUIApplicationComponent;
import rs.sol.soloist.server.guiconfiguration.components.GUIButtonComponent;
import rs.sol.soloist.server.guiconfiguration.components.GUILabelComponent;
import rs.sol.soloist.server.guiconfiguration.components.GUIPanelComponent;
import rs.sol.soloist.server.guiconfiguration.construction.GUIComponentBinding;
import rs.sol.soloist.server.guiconfiguration.elementcomponents.GUICollectionInput;
import rs.sol.soloist.server.guiconfiguration.elementcomponents.GUIElementComponent;
import rs.sol.soloist.server.guiconfiguration.elementcomponents.GUIListWidget;
import rs.sol.soloist.server.guiconfiguration.elementcomponents.GUISlotEditorKind;
import rs.sol.soloist.server.guiconfiguration.elementcomponents.GUISlotValueInput;
import rs.sol.soloist.server.guiconfiguration.layout.CellLayoutData;
import rs.sol.soloist.server.guiconfiguration.layout.TableLayoutData;
import rs.sol.soloist.server.guiconfiguration.layout.VerticalAlignment;
import rs.sol.soloist.server.guiconfiguration.nonvisualcompoments.GUIFindAllInstancesSAPComponent;
import rs.sol.soloist.server.guiconfiguration.style.GUIContext;
import rs.sol.soloist.server.guiconfiguration.style.GUINumberTextFeature;
import rs.sol.soloist.server.guiconfiguration.style.GUIObjectSetting;
import rs.sol.soloist.server.guiconfiguration.style.GUIPictureFeature;
import rs.sol.soloist.server.guiconfiguration.style.GUITextFeature;
import rs.sol.soloist.server.server.SoloistServiceServlet;
 
public enum PersonsAndBankAccounts implements Initializer{
 
	INSTANCE;
 
	@Override
	public void init() throws InitializerFailedException
	{
		GUIApplicationComponent page = new GUIApplicationComponent();
		page.name.set(Text.fromString("PersonsAndBankAccounts")); 
		SoloistServiceServlet.registerApplication(page);
 
		GUIContext context = createContextAndStyles(); 
		page.context.set(context);
 
		GUIPanelComponent root = GUIPanelComponent.createFlow(page);
 
		GUILabelComponent title = GUILabelComponent.create(root, "Persons and Bank Accounts");
		title.styleName.set(Text.fromString("titleStyle"));
 
		GUIPanelComponent topPanel = GUIPanelComponent.createFlow(root);
		topPanel.styleName.set(Text.fromString("topPanel"));
 
		GUIPanelComponent table = GUIPanelComponent.createTable(topPanel);
 
		// first row
		GUILabelComponent.create(table, "Persons", 0, 0);
		GUILabelComponent.create(table, "Person's Bank Accounts", 0, 1);
		GUILabelComponent.create(table, "Account Details", 0, 2);
 
		// second row
		GUIFindAllInstancesSAPComponent allPersons = GUIFindAllInstancesSAPComponent.create(root, Person.FQ_TYPE_NAME);
		GUIElementComponent personsList = GUIElementComponent.createInput(table, new GUIListWidget(), new GUICollectionInput(), 1, 0); // shows all persons
		GUIComponentBinding.create(allPersons.value, GUICollectionInput.get(personsList).collection);
		CellLayoutData.setSize(personsList, "250px", "300px");
		personsList.styleName.set(Text.fromString("listWidget"));
		GUIElementComponent accountsList = GUIElementComponent.createInput(table, new GUIListWidget(), GUISlotValueInput.create(Person.PROPERTIES.accounts), 1, 1); // shows bank accounts for selected person
		CellLayoutData.setSize(accountsList, "250px", "300px");
		accountsList.styleName.set(Text.fromString("listWidget"));
		GUIPanelComponent accountDetailsTable = GUIPanelComponent.createTable(table);
		TableLayoutData.setRowColumn(accountDetailsTable, 1, 2); // place the accountDetailsTable
		TableLayoutData.setAlignment(accountDetailsTable, VerticalAlignment.TOP);
 
		// third row
		GUIButtonComponent createAccountButton = GUIButtonComponent.create(table, "Create Account for Person", new CreateAccountForPerson(), 2, 0);
		CmdDestroyObject destroyCmd = new CmdDestroyObject();
		destroyCmd.type.set(Text.fromString(BankAccount.FQ_TYPE_NAME));
		GUIButtonComponent destroyAccountButton = GUIButtonComponent.create(table, "Delete Account", destroyCmd, 2, 1);
 
		// let's fill in the accoutDetailsTable
		GUILabelComponent.create(accountDetailsTable, "Number:", 0, 0);
		GUILabelComponent.create(accountDetailsTable, "Amount:", 1, 0);
		GUILabelComponent.create(accountDetailsTable, "Bank name:", 2, 0);
 
		GUIElementComponent numberEditor = GUIElementComponent.createSlotEditor(accountDetailsTable, BankAccount.PROPERTIES.number, 0, 1);
		GUIElementComponent amountEditor = GUIElementComponent.createSlotEditor(accountDetailsTable, BankAccount.PROPERTIES.amount, 1, 1);
		GUIElementComponent bankNameEditor = GUIElementComponent.createSlotEditor(accountDetailsTable, BankAccount.PROPERTIES.bankName, 2, 1);
 
		// let's bind the components
		GUIComponentBinding.create(personsList.value, GUISlotValueInput.get(accountsList).element); // account list will be populated for the selected person in the persons list
		GUIComponentBinding.create(personsList.value, createAccountButton, CreateAccountForPerson.PROPERTIES.person); // this specifies that account will be created for selected person
		GUIComponentBinding.create(accountsList.value, destroyAccountButton, CmdDestroyObject.PROPERTIES.input); // this specifies that selected account will be destroyed
		GUIComponentBinding.create(accountsList.value, GUISlotEditorKind.get(numberEditor).element);
		GUIComponentBinding.create(accountsList.value, GUISlotEditorKind.get(amountEditor).element);
		GUIComponentBinding.create(accountsList.value, GUISlotEditorKind.get(bankNameEditor).element);
	}
 
	private GUIContext createContextAndStyles()
	{
		GUIContext context = new GUIContext();
		context.supercontext.set(DefaultContextInit.getRoot());
 
		GUIObjectSetting bankAccount = GUIObjectSetting.create(context, BankAccount.CLASSIFIER);
		GUITextFeature.createName(bankAccount, BankAccount.PROPERTIES.number);
		GUITextFeature.createSeparator(bankAccount, "/", true);
		GUINumberTextFeature.createDescription(bankAccount, BankAccount.PROPERTIES.amount);
		GUIPictureFeature.createSmallIcon(bankAccount, "images/icons/bankaccount.png");
 
		GUIObjectSetting person = GUIObjectSetting.create(context, Person.CLASSIFIER);
		GUITextFeature.createName(person, Person.PROPERTIES.name);
		GUITextFeature.createSeparator(person, "Age:", true);
		GUITextFeature.createDescription(person, Person.PROPERTIES.age);
		GUIPictureFeature.createSmallIcon(person, "images/icons/person.png");
		return context;
	}
 
}
Print/export